Chapter 3: sparse arrays and queues

Keywords: data structure

Chapter 3: sparse arrays and queues

1. Sparse array

1.1 actual demand

  • The Gobang program has the functions of saving, exiting and continuing the upper board

  • Because many values of the two-dimensional array are the default value of 0, many meaningless data are recorded. We convert them into sparse arrays for storage

1.2. Sparse array application

1.2.1 sparse array processing method

  • Sparse array records the rows, columns and values of elements with different values in a small-scale array, so as to reduce the size of the program

  • Sparse array is also a two-dimensional array. The number of rows is determined by the data of the original array, and the number of columns is generally 3 columns

  • Sparse array

    first line

    Record the number of rows and columns in the original array, and the number of non-zero values

    • First column: the number of rows of the original array
    • Second column: the number of columns of the original array
    • Column 3: how many non-zero values does the original array have
  • Subsequent rows are recorded in the original array

    Value that is not zero (x)

    The number of rows, columns, and the value of x

    • First column: the number of rows of x in the original array
    • Second column: the number of columns of x in the original array
    • Column 3: value of x

1.2.2. Examples

  • The original two-dimensional array is large, and the occupied space is reduced after compression

1.3 application examples

1.3.1 train of thought analysis

  • Use a sparse array to preserve a two-dimensional array similar to the previous one (chessboard, map, etc.)
  • Save the sparse array, and you can restore the original number of two-dimensional arrays

1.3.2 code implementation

  • code
public class SparseArray {

    public static void main(String[] args) {
        // Create an original two-dimensional array 11 * 11
        // 0: indicates no chess pieces, 1 indicates sunspots, and 2 indicates bluestones
        int chessArr1[][] = new int[11][11];
        chessArr1[1][2] = 1;
        chessArr1[2][3] = 2;
        chessArr1[4][5] = 2;
        // Output the original two-dimensional array
        System.out.println("Original two-dimensional array~~");
        for (int[] row : chessArr1) {
            for (int data : row) {
                System.out.printf("%d\t", data);
            }
            System.out.println();
        }

        // Thinking of converting two-dimensional array to sparse array
        // 1. First traverse the two-dimensional array to get the number of non-0 data
        int sum = 0;
        for (int i = 0; i < chessArr1.length; i++) {
            for (int j = 0; j < chessArr1[i].length; j++) {
                if (chessArr1[i][j] != 0) {
                    sum++;
                }
            }
        }

        // 2. Create the corresponding sparse array
        int sparseArr[][] = new int[sum + 1][3];
        // Assign values to sparse arrays
        sparseArr[0][0] = chessArr1.length;
        sparseArr[0][1] = chessArr1[0].length;
        sparseArr[0][2] = sum;

        // Traverse the two-dimensional array and store non-0 values in sparseArr
        int count = 0; // count is used to record the number of non-zero data
        for (int i = 0; i < chessArr1.length; i++) {
            for (int j = 0; j < chessArr1[i].length; j++) {
                if (chessArr1[i][j] != 0) {
                    count++;
                    sparseArr[count][0] = i;
                    sparseArr[count][1] = j;
                    sparseArr[count][2] = chessArr1[i][j];
                }
            }
        }

        // Output sparse array form
        System.out.println();
        System.out.println("Get the sparse array as~~~~");
        for (int i = 0; i < sparseArr.length; i++) {
            System.out.printf("%d\t%d\t%d\n", sparseArr[i][0], sparseArr[i][1], sparseArr[i][2]);
        }
        System.out.println();

        // Restore the sparse array to the original two-dimensional array
        /*
         * 1. First read the first row of the sparse array and create the original two-dimensional array according to the data in the first row, such as chessArr2 = int [11][11] 2
         * After reading a few rows of data from the sparse array, assign it to the original two-dimensional array
         */

        // 1. First read the first row of the sparse array and create the original two-dimensional array according to the data of the first row

        int chessArr2[][] = new int[sparseArr[0][0]][sparseArr[0][1]];

        // 2. Read the data of the last few rows of the sparse array (starting from the second row) and assign it to the original two-dimensional array

        for (int i = 1; i < sparseArr.length; i++) {
            chessArr2[sparseArr[i][0]][sparseArr[i][1]] = sparseArr[i][2];
        }

        // Output recovered 2D array
        System.out.println();
        System.out.println("Restored 2D array");

        for (int[] row : chessArr2) {
            for (int data : row) {
                System.out.printf("%d\t", data);
            }
            System.out.println();
        }
    }

}

  • Program running results
Original two-dimensional array~~
0	0	0	0	0	0	0	0	0	0	0	
0	0	1	0	0	0	0	0	0	0	0	
0	0	0	2	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	2	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	

Get the sparse array as~~~~
11	11	3
1	2	1
2	3	2
4	5	2

Restored 2D array
0	0	0	0	0	0	0	0	0	0	0	
0	0	1	0	0	0	0	0	0	0	0	
0	0	0	2	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	2	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	

1.4 after class exercises

  • Based on the above, save the sparse array to disk, such as map.data
  • When restoring the original array, read map.data to restore

2. Queue

2.1 queue usage scenario

  • Cases of Bank Queuing:

2.2 queue introduction

  • Queue is a sequential list, which can be implemented by array or linked list.
  • Follow the principle of first in first out, that is, the data stored in the queue should be taken out first, and the data stored later should be taken out later
  • Schematic: (use array to simulate queue schematic)

2.3 array simulation queue

2.3.1 train of thought analysis

  • maxSize: queue capacity (length of array)
  • arr: array of simulated queues
  • front: points to the previous element of the queue header element, with an initial value of - 1
  • rear: refers to the element at the end of the queue. The initial value is - 1

  • basic operation
    • Empty queue: front == rear
    • The queue is full: rear == (maxSize - 1), that is, whether the rear has pointed to the last position of the array
    • Number of queue elements: rear - front
    • Queue join: join only when the queue is not satisfied, arr[++rear] = value
    • Queue exit: only when the queue is not empty can you exit the queue, return arr[front + +]

2.3.2 code implementation

  • Definition of queue
// Use arrays to simulate queues - write an ArrayQueue class
class ArrayQueue {
    private int maxSize; // Represents the maximum capacity of the array
    private int front; // Queue header
    private int rear; // Queue tail
    private int[] arr; // This data is used to store data and simulate the queue

    // Constructor to create a queue
    public ArrayQueue(int arrMaxSize) {
        maxSize = arrMaxSize;
        arr = new int[maxSize];
        front = -1; // Point to the queue header and analyze that front is the previous position pointing to the queue header
        rear = -1; // Data pointing to the end of the queue (that is, the last data of the queue)
    }

    // Determine whether the queue is full
    public boolean isFull() {
        return rear == maxSize - 1;
    }

    // Determine whether the queue is empty
    public boolean isEmpty() {
        return rear == front;
    }

    // Add data to queue
    public void addQueue(int n) {
        // Determine whether the queue is full
        if (isFull()) {
            System.out.println("The queue is full and data cannot be added~");
            return;
        }
        rear++; // Move rear
        arr[rear] = n;
    }

    // Get the data of the queue and get out of the queue
    public int getQueue() {
        // Judge whether the queue is empty
        if (isEmpty()) {
            // By throwing an exception
            throw new RuntimeException("The queue is empty and data cannot be retrieved");
        }
        front++; // front backward
        return arr[front];

    }

    // Displays all data for the queue
    public void showQueue() {
        // ergodic
        if (isEmpty()) {
            System.out.println("The queue is empty and there is no data~~");
            return;
        }
        for (int i = front + 1; i <= rear; i++) {
            // Placeholders can also be used in Java
            System.out.printf("arr[%d]=%d\n", i, arr[i]);
        }
    }

    // The header data of the queue is displayed. Note that it is not taken out
    public int headQueue() {
        // judge
        if (isEmpty()) {
            throw new RuntimeException("The queue is empty and there is no data~~");
        }
        return arr[front + 1];
    }
}
  • Test code
public class ArrayQueueDemo {

    public static void main(String[] args) {
        // Test one
        // Create a queue
        ArrayQueue queue = new ArrayQueue(3);
        char key = ' '; // Receive user input
        Scanner scanner = new Scanner(System.in);//
        boolean loop = true;
        // Output a menu
        while (loop) {
            System.out.println("s(show): Show queue");
            System.out.println("e(exit): Exit program");
            System.out.println("a(add): Add data to queue");
            System.out.println("g(get): Fetch data from queue");
            System.out.println("h(head): View data of queue header");
            System.out.println();
            key = scanner.next().charAt(0);// Receive a character
            switch (key) {
                case 's':
                    queue.showQueue();
                    break;
                case 'a':
                    System.out.println("Output a number");
                    int value = scanner.nextInt();
                    queue.addQueue(value);
                    break;
                case 'g': // Fetch data
                    try {
                        int res = queue.getQueue();
                        System.out.printf("The extracted data is%d\n", res);
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'h': // View data of queue header
                    try {
                        int res = queue.headQueue();
                        System.out.printf("The data in the queue header is%d\n", res);
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'e': // sign out
                    scanner.close();
                    loop = false;
                    break;
                default:
                    break;
            }
        }

        System.out.println("Program exit~~");
    }

}

  • Program running results
s(show): Show queue
e(exit): Exit program
a(add): Add data to queue
g(get): Fetch data from queue
h(head): View data of queue header

s
 The queue is empty and there is no data~~
s(show): Show queue
e(exit): Exit program
a(add): Add data to queue
g(get): Fetch data from queue
h(head): View data of queue header

a
 Output a number
1
s(show): Show queue
e(exit): Exit program
a(add): Add data to queue
g(get): Fetch data from queue
h(head): View data of queue header

a
 Output a number
2
s(show): Show queue
e(exit): Exit program
a(add): Add data to queue
g(get): Fetch data from queue
h(head): View data of queue header

a
 Output a number
3
s(show): Show queue
e(exit): Exit program
a(add): Add data to queue
g(get): Fetch data from queue
h(head): View data of queue header

s
arr[0]=1
arr[1]=2
arr[2]=3
s(show): Show queue
e(exit): Exit program
a(add): Add data to queue
g(get): Fetch data from queue
h(head): View data of queue header

a
 Output a number
4
 The queue is full and data cannot be added~
s(show): Show queue
e(exit): Exit program
a(add): Add data to queue
g(get): Fetch data from queue
h(head): View data of queue header

g
 The extracted data is 1
s(show): Show queue
e(exit): Exit program
a(add): Add data to queue
g(get): Fetch data from queue
h(head): View data of queue header

g
 The extracted data is 2
s(show): Show queue
e(exit): Exit program
a(add): Add data to queue
g(get): Fetch data from queue
h(head): View data of queue header

g
 The extracted data is 3
s(show): Show queue
e(exit): Exit program
a(add): Add data to queue
g(get): Fetch data from queue
h(head): View data of queue header

g
 The queue is empty and data cannot be retrieved
s(show): Show queue
e(exit): Exit program
a(add): Add data to queue
g(get): Fetch data from queue
h(head): View data of queue header

2.4 array model ring queue

2.4.1 raising questions

  • At present, arrays cannot be used once, which does not achieve the effect of reuse, resulting in a waste of memory space
  • This array is improved into a ring queue by using the algorithm (modulus:%)

2.4.2 train of thought analysis

  • The front queue is optimized and transformed into a ring queue (realized by taking a module)
  • maxSize: queue capacity (length of array)
  • arr: array of simulated queues
  • front: points to the queue header element, with an initial value of 0
  • rear: refers to the last element at the end of the queue. The initial value is 0

  • basic operation
    • Empty queue: front == rear
    • Queue full:
      • Why do you want to free up the space of an element after the rear and before the front? Because if an element is not empty, the queue empty condition is: front == rear, and the queue full condition is also: front == rear, which is ambiguous!
      • Queue capacity: because an element is vacated, the queue capacity becomes (maxSize - 1)
      • When the space of an element is vacated, how to judge the full space? When there is one element left, the queue is full, so the judgment condition is (rear + 1)% maxsize = = front
    • Number of queue elements:
      • Calculation formula: (rear + maxsize - front)% maxsize, think like this:
      • When the rear is larger than the front, (rear -front) > 0, the ring structure has not been formed, and (rear -front) is the number of queue elements
      • When rear is smaller than front, that is, (rear -front) < 0, a ring structure has been formed, (rear -front) indicates how many elements of the array are full (negative number), (rear + maxSize)-
        front) is the number of queue elements
      • To sum up: (rear + maxsize - front)% maxsize
    • Queue in:
      • First, you can join the team only if the queue is dissatisfied
      • Since rear points to the next element at the end of the queue, you can set it directly: arr[rear] = value
      • Next, the rear should be moved back one position: rear = (rear + 1)% maxsize
      • The purpose of modulo is to prevent the array from going out of bounds and make the pointer return to the first element of the array
    • Queue out:
      • First, the queue cannot be left empty
      • Since the front directly points to the queue header element, you can directly return the element: int value = arr[front]
      • Next, front should move back one position: front = (front + 1)% maxsize
      • The purpose of modulo is to prevent the array from going out of bounds and make the pointer return to the first element of the array

2.4.3 code implementation

  • Implementation of ring queue
class CircleArray {
    private int maxSize; // Represents the maximum capacity of the array
    // Adjust the meaning of the front variable: front points to the first element of the queue, that is, arr[front] is the first element of the queue
    // Initial value of front = 0
    private int front;
    // Make an adjustment to the meaning of the rear variable: the rear variable points to the next position of the last element of the queue, because you want to free up a space as a convention
    // Initial value of rear = 0
    private int rear; // Queue tail
    private int[] arr; // This data is used to store data and simulate the queue

    public CircleArray(int arrMaxSize) {
        maxSize = arrMaxSize;
        arr = new int[maxSize];
    }

    // Determine whether the queue is full
    public boolean isFull() {
        return (rear + 1) % maxSize == front;
    }

    // Determine whether the queue is empty
    public boolean isEmpty() {
        return rear == front;
    }

    // Add data to queue
    public void addQueue(int n) {
        // Determine whether the queue is full
        if (isFull()) {
            System.out.println("The queue is full and data cannot be added~");
            return;
        }
        // Add data directly
        arr[rear] = n;
        // Move the rear, and here you must consider taking the mold
        rear = (rear + 1) % maxSize;
    }

    // Get the data of the queue and get out of the queue
    public int getQueue() {
        // Judge whether the queue is empty
        if (isEmpty()) {
            // By throwing an exception
            throw new RuntimeException("The queue is empty and data cannot be retrieved");
        }
        // Here, we need to analyze that front is the first element pointing to the queue
        // 1. First keep the value corresponding to front to a temporary variable
        // 2. Move the front backward and consider taking the mold
        // 3. Return temporarily saved variables
        int value = arr[front];
        front = (front + 1) % maxSize;
        return value;

    }

    // Displays all data for the queue
    public void showQueue() {
        // ergodic
        if (isEmpty()) {
            System.out.println("The queue is empty and there is no data~~");
            return;
        }
        // Idea: start traversing from front, and how many elements are traversed
        // Use your head
        for (int i = front; i < front + size(); i++) {
            System.out.printf("arr[%d]=%d\n", i % maxSize, arr[i % maxSize]);
        }
    }

    // Find the number of valid data in the current queue
    public int size() {
        // rear = 2
        // front = 1
        // maxSize = 3
        return (rear + maxSize - front) % maxSize;
    }

    // The header data of the queue is displayed. Note that it is not taken out
    public int headQueue() {
        // judge
        if (isEmpty()) {
            throw new RuntimeException("The queue is empty and there is no data~~");
        }
        return arr[front];
    }
}

  • Test code
public class CircleArrayQueueDemo {

    public static void main(String[] args) {

        // Test one
        System.out.println("Test array simulation ring queue case~~~");

        // Create a ring queue
        CircleArray queue = new CircleArray(4); // Description set 4, and the maximum valid data of its queue is 3
        char key = ' '; // Receive user input
        Scanner scanner = new Scanner(System.in);//
        boolean loop = true;
        // Output a menu
        while (loop) {
            System.out.println("s(show): Show queue");
            System.out.println("e(exit): Exit program");
            System.out.println("a(add): Add data to queue");
            System.out.println("g(get): Fetch data from queue");
            System.out.println("h(head): View data of queue header");
            System.out.println();
            key = scanner.next().charAt(0);// Receive a character
            switch (key) {
                case 's':
                    queue.showQueue();
                    break;
                case 'a':
                    System.out.println("Output a number");
                    int value = scanner.nextInt();
                    queue.addQueue(value);
                    break;
                case 'g': // Fetch data
                    try {
                        int res = queue.getQueue();
                        System.out.printf("The extracted data is%d\n", res);
                    } catch (Exception e) {
                        // TODO: handle exception
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'h': // View data of queue header
                    try {
                        int res = queue.headQueue();
                        System.out.printf("The data in the queue header is%d\n", res);
                    } catch (Exception e) {
                        // TODO: handle exception
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'e': // sign out
                    scanner.close();
                    loop = false;
                    break;
                default:
                    break;
            }
        }
        System.out.println("Program exit~~");
    }

}

  • Program running results
Test array simulation ring queue case~~~
s(show): Show queue
e(exit): Exit program
a(add): Add data to queue
g(get): Fetch data from queue
h(head): View data of queue header

a
 Output a number
1
s(show): Show queue
e(exit): Exit program
a(add): Add data to queue
g(get): Fetch data from queue
h(head): View data of queue header

a
 Output a number
2
s(show): Show queue
e(exit): Exit program
a(add): Add data to queue
g(get): Fetch data from queue
h(head): View data of queue header

a
 Output a number
3
s(show): Show queue
e(exit): Exit program
a(add): Add data to queue
g(get): Fetch data from queue
h(head): View data of queue header

s
arr[0]=1
arr[1]=2
arr[2]=3
s(show): Show queue
e(exit): Exit program
a(add): Add data to queue
g(get): Fetch data from queue
h(head): View data of queue header

a
 Output a number
4
 The queue is full and data cannot be added~
s(show): Show queue
e(exit): Exit program
a(add): Add data to queue
g(get): Fetch data from queue
h(head): View data of queue header

g
 The extracted data is 1
s(show): Show queue
e(exit): Exit program
a(add): Add data to queue
g(get): Fetch data from queue
h(head): View data of queue header

g
 The extracted data is 2
s(show): Show queue
e(exit): Exit program
a(add): Add data to queue
g(get): Fetch data from queue
h(head): View data of queue header

s
arr[2]=3
s(show): Show queue
e(exit): Exit program
a(add): Add data to queue
g(get): Fetch data from queue
h(head): View data of queue header

g
 The extracted data is 3
s(show): Show queue
e(exit): Exit program
a(add): Add data to queue
g(get): Fetch data from queue
h(head): View data of queue header

g
 The queue is empty and data cannot be retrieved
s(show): Show queue
e(exit): Exit program
a(add): Add data to queue
g(get): Fetch data from queue
h(head): View data of queue header

Posted by Michael Lasky on Wed, 24 Nov 2021 07:35:42 -0800