2021-10-13 I. array and queue

Keywords: Java Algorithm data structure

1. Sparse array

1.1 what is a sparse array

  • Sparse array, first of all, remove the sparse array. It is understood that you, who write the program, have thinning and less hair.
  • For example, a chess board can be represented by a binary array. For this chess card (there are only three kinds of data, 0 means no chess pieces, 1 means black chess, and 2 means white chess), we can only extract the positions of black and white chess to form a sparse array.

1.2 application scenarios

  • For example, it can be used when there are large quantities and most of them are duplicate values (chess, cards, maps, etc.)

1.3 graphic analysis

  1. First, create a new array to record how many rows, columns and different values the array has
  2. Then, the columns, rows and values (the color of the chess pieces) in the element are recorded in a small-scale array, so as to reduce the size of the program.

1.4 code implementation and ideas

2D array to sparse array
Idea:

  1. The first thing to note is that both rows and columns are designed from scratch.
  2. Traverse the original binary array and obtain the number sum of valid values [1 (black chess) and 2 (white chess)]
  3. Then create a sparse array sparsearray[sum + 1][3] according to sum
    Note: because the first one-dimensional array of the sparse array needs to save the number of rows, columns and valid values of the original array, the number of one-dimensional arrays of the sparse array is sum+1
  4. Store the valid data of the original two-dimensional array into a sparse array
    (valid data: row, column and value of element [1, 2])

Sparse array to 2D array
Idea:

  1. First, create the original two-dimensional array according to the first row of the sparse array
  2. Read the row, column and value of the sparse array from the second row, and assign the value back to the original two-dimensional array

The code includes serialization and deserialization. If not, you can see it Java Basics

code implementation

public class Demo1 {

    public final static String RESOURCE_PATH = "";


    /**
     * 2D array to sparse array
     */
    private static int[][] arr2Sparse(int[][] chessArr) {
        // Step 1: total number of valid values obtained
        int sum = 0;
        for (int[] row : chessArr) {
            for (int data : row) {
                if (data != 0) {
                    sum++;
                }
            }
        }
        System.out.println("Total valid values obtained:" + sum); // Total valid values obtained: 3

        // Step 2: valid data initialization of sparse array
        int[][] sparseArray = new int[sum + 1][3];
        // Initialize valid data for sparse arrays
        sparseArray[0][0] = 11;
        sparseArray[0][1] = 11;
        sparseArray[0][2] = sum;

        // Traverse the original binary array and put valid pieces (non-0) into sparseArray
        // i represents row and j represents column
        int count = 0; // Record the number of effective pieces
        for (int i = 0; i < chessArr.length; i++) {
            for (int j = 0; j < chessArr.length; j++) {
                if (chessArr[i][j] != 0) {
                    count++;
                    sparseArray[count][0] = i;
                    sparseArray[count][1] = j;
                    sparseArray[count][2] = chessArr[i][j];
                }
            }
        }
        return sparseArray;
    }


    /**
     * Sparse array to 2D array (restore chessboard)
     */
    private static int[][] sparse2Arr(int[][] sparseArray) {
        int[][] chessArr = new int[sparseArray[0][0]][sparseArray[0][1]];
        // The second line starts the assignment
        for (int i = 1; i < sparseArray.length; i++) {
            // Representation: the valid value of each sparse row is copied to the original row and column
            chessArr[sparseArray[i][0]][sparseArray[i][1]] = sparseArray[i][2];
        }
        return chessArr;
    }



    /**
     * Traversal tool class
     */
    private static void print(int[][] array) {
        for (int[] row : array) {
            for (int data : row) {
                System.out.printf("%d\t", data);
            }
            System.out.println();
        }
    }


    public static void main(String[] args) {
        // Create an original chess card size of 11 * 11
        // 1 black, 2 white, 0 no
        int[][] chessArr = new int[11][11];
        // Drop a few pieces at random
        chessArr[1][2] = 1;
        chessArr[3][4] = 2;
        chessArr[5][7] = 1;
        // Output original binary array (chess and cards)
        System.out.println("Output my chessboard:");
        // ergodic
        print(chessArr);

        System.out.println("------------------------------------2D array to sparse array-----------------------------------");

        int[][] sparseArray = arr2Sparse(chessArr);

        System.out.println("Sparse array:");
        print(sparseArray);
        System.out.println("------------------------------------Sparse array to 2D array(Restore chessboard)-----------------------------------");

        // Sparse array to original array row * column
        int[][] chessArr2 = sparse2Arr(sparseArray);

        // ergodic
        System.out.println("Restored 2D array");
        print(chessArr2);

        // =====================The following is serialization, which can be ignored=====================

        // Sparse serialization
        sparseSerialize(sparseArray);

        // Sparse deserialization
        int[][] arr = (int[][]) sparseDSerialize();
        if (arr != null) {
            System.out.println("Finally, get the class class type" + arr.getClass().getName());
            print(arr);
        }

    }
    /**
     * Serialization tool class
     */
    private static void sparseSerialize(int[][] array) {
        ObjectOutputStream oos = null;
        try {
            oos = new ObjectOutputStream(new FileOutputStream(RESOURCE_PATH));
            oos.writeObject(array);
            oos.flush();
        } catch (Exception e) {
            e.getStackTrace();
        } finally {
            try {
                if (oos != null) {
                    oos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * Serialization tool class
     */
    private static Object sparseDSerialize() {
        ObjectInputStream ois = null;
        Object arr;
        try {
            ois = new ObjectInputStream(new FileInputStream(RESOURCE_PATH));
            arr = ois.readObject();
            return arr;
        } catch (Exception e) {
            e.getStackTrace();
        } finally {
            try {
                if (ois != null) {
                    ois.close();
                }
            } catch (Exception e2) {
                e2.getStackTrace();
            }
        }
        return null;
    }
}

Output results:

Output my chessboard:
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	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	1	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	
------------2D array to sparse array-------------
Total valid values obtained: 3
 Sparse array:
11	11	3	
1	2	1	
3	4	2	
5	7	1	
----------Sparse array to 2D array(Restore chessboard)----------
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	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	1	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	

2. Queue (array simulation)

2.1 basic description of queue

  1. Queue is a sequential list, which can be implemented by array or linked list
  2. Follow the principle of first in, first out. First store the data, first take it out, then store it and then take it out

2.2 array simulation queue


Resolution:

  1. The queue itself has a sequence table. If the array structure is used to store the data of the queue, the declaration of the queue array is as shown in the figure above, where maxSize is the maximum capacity of the queue.
  2. Because the output and input of the queue are processed from both ends respectively, two variables front and rear are required to record the subscripts at both ends of the queue respectively. The front will change with the data output, while the rear will change with the data input.

2.3 design ideas

Explain the two operations of joining and leaving the queue (preconditions: the initial values of front and rear point to the front of the first number in the queue, that is, front=rear=-1)
When we store data into a queue, it is called addQueue. The processing of addQueue requires two steps:

  1. First, judge whether the queue is full (rear == maxSize - 1 indicates that the queue is full). If it is full, the data cannot be stored in the queue.
  2. Then move the tail pointer back: rear + 1 and put the data into the queue.

When we take data out of the queue (out of the queue) as getQueue, the processing of getQueue needs two steps:

  1. First, judge whether the queue is empty (rear == front indicates that the queue is empty). If it is empty, data cannot be retrieved.
  2. Then move the header pointer back: front + 1, take the data out of the queue, and finally reset the position of the data to 0.

2.4 code implementation

// Queue entity class
public class ArrayQueue {
    private final int maxSize;// Maximum capacity of the array
    private int front;  // Queue header
    private int rear;    // End of column
    private final int[] arr;    // This array is used to simulate the data stored in the queue

    // Create queue constructor
    public ArrayQueue(int arrMaxSize) {
        maxSize = arrMaxSize;
        arr = new int[arrMaxSize];
        front = -1;// Point to the queue header. The initialized front is the previous position of the queue header
        rear = -1; // Point to the end of the queue, which means the position of the last data in the queue. The initial value is also the previous position of the queue head
    }

    // Determine whether the queue is full
    public boolean isFull() {
        return rear == maxSize - 1;// The end of the queue = = the last data of the array indicates that the queue is full
    }

    // Determine whether your queue is empty
    public boolean isEmpty() {
        return front == rear;// If the head and tail are equal, there is no data
    }

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

    // Get queue data (out of queue)
    public int getQueue() {
        // Determine whether the queue is empty
        if (isEmpty()) {
            // Throw null by exception
            throw new RuntimeException("The queue is empty, unable to fetch data~~~");
        }
        front++;// front backward
        int result = arr[front]; // Take out the value of the current queue
        arr[front] = 0;// Reset the removed position to 0
        return result;
    }

    // Displays all data for the queue
    public void showQueue() {
        // Air judgment
        if (isEmpty()) {
            System.out.println("Queue is empty,cannot display data~~~~");
            return;
        }
        // ergodic
        for (int i = 0; i < arr.length; i++) {
            System.out.printf("arr[%d]=%d\n", i, arr[i]);
        }
    }

    // Show header queue instead of fetch
    public int headQueue() {
        // Air judgment
        if (isEmpty()) {
            // Throw null by exception
            throw new RuntimeException("The queue is empty, unable to fetch data~~~");
        }
        // display
        return arr[front + 1];// The reason for adding one here is that at the beginning, initialization points to the previous one of the queue header
    }

}

// Test class
public class Demo2 {
    public static void main(String[] args) {
        //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");
            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) {
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'e': //sign out
                    scanner.close();
                    loop = false;
                    break;
                default:
                    break;
            }
        }

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

}

2.5 problems with this queue

  • At present, the designed queue can only be used once (because the array can only be used once), which does not achieve the reuse effect
  • Therefore, we need to improve the algorithm of this array into a ring queue (modulus%)

2.6 design idea of ring queue (there are many implementation methods for reference only)

  1. Front variable adjustment: the initial value of front = 0, which directly points to the first number of queues.
  2. Adjustment of rear variable: the initial value of rear = 0. Always point to the last position in the queue (the logic of joining the queue here is to join the queue first and then + +)
  3. The formula to judge whether the queue is full is (rear + 1)% maxsize = = front. Here, we want to make a space available as a convention to judge whether the queue is full. For example, if the array length is 5, it will be judged that it is full by storing 4 data (a space must be wasted, otherwise there is no way to distinguish between empty and full)
  4. The formula for judging that the queue is empty, rear == front, (if front reaches the position of rear, it means that the queue is finished)
  5. Number of valid data in the queue (rear + maxsize - front)% maxsize
    As for the formula derivation of the fifth point, under normal circumstances, the number of effective data should be rear front, but the subscript of rear may be less than front in the ring queue. Therefore, maxSize is added here to ensure that rear must be greater than front, and then the module is taken to achieve the effect of calculating effective data.

2.7 code implementation

// Ring queue entity class
public class CircleArrayQueue {
    // Maximum capacity of the array
    private final int maxSize;
    private final int[] arr;
    // Front points to the first element of the queue, that is, arr[front] is the first element of the queue
    private int front;
    // rear points to the next position of the last element of the queue
    private int rear;

    // Create queue constructor
    public CircleArrayQueue(int arrMaxSize) {
        maxSize = arrMaxSize;
        arr = new int[arrMaxSize];
        // The default value of front rear is 0, and the declared default value is 0, so there is no need to assign values repeatedly
    }

    // Determine whether the queue is full
    public boolean isFull() {
        // The ring queue has a vacant space at the end of the queue to judge whether it is full or not
        return (rear + 1) % maxSize == front;
    }

    // Determine whether your queue is empty
    public boolean isEmpty() {
        // If the head and tail are equal, there is no data
        return front == rear;
    }

    // Add data to queue
    public void addQueue(int n) {
        // Determine whether the queue is full
        if (isFull()) {
            System.out.println("The queue is full,Unable to add data~~~~");
            return;
        }
        // Straight in
        arr[rear] = n;
        // When the real moves backward, the subscript out of bounds module (ring) must be considered
        rear = (rear + 1) % maxSize;
    }

    // Get queue data (out of queue)
    public int getQueue() {
        // Determine whether the queue is empty
        if (isEmpty()) {
            // Throw null by exception
            throw new RuntimeException("The queue is empty, unable to fetch data~~~");
        }
        // front is the first element pointing to the queue
        // First save the front value to a temporary variable for returning
        // Then move back
        int value = arr[front];
        front = (front + 1) % maxSize;
        return value;
    }

    // Displays all data for the queue
    public void showQueue() {
        // Air judgment
        if (isEmpty()) {
            System.out.println("Queue is empty,cannot display data~~~~");
            return;
        }
        // Traversal (from beginning to end + number of valid data)
        for (int i = front; i < front + size(); i++) {
            System.out.printf("arr[%d]=%d\n", i % maxSize, arr[i % maxSize]);
        }
    }

    // Calculate the number of valid data
    public int size() {
        return (rear - front + maxSize) % maxSize;
    }

    // Show header queue instead of fetch
    public int headQueue() {
        // Air judgment
        if (isEmpty()) {
            // Throw null by exception
            throw new RuntimeException("The queue is empty, unable to fetch data~~~");
        }
        // display
        return arr[front];
    }
}

// Test class
public class Demo3 {
    public static void main(String[] args) {
        //Create a queue
        CircleArrayQueue queue = new CircleArrayQueue(4);// The valid data 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");
            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~~");
    }
}

General catalogueNext
Data structure (Java) directoryUnfinished to be continued

Posted by gabeanderson on Fri, 15 Oct 2021 12:25:46 -0700