DSA_ Sparse arrays and queues (java data structures and algorithms)

Sparse sparseArray array

Let's take a look at the actual needs

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

Analyze the problem:

Because many values of the two-dimensional array are the default value of 0, many meaningless data are recorded. - > sparse array.

Basic introduction

When most elements in an array are 0 or an array with the same value, you can use a sparse array to save the array.

The processing method of sparse array is:

  1. How many rows and columns are there in the record array? How many different values are there

  2. The rows, columns and values of elements with different values are recorded in a small-scale array, so as to reduce the size of the program

Sparse array example

Application examples

  1. Use a sparse array to preserve a two-dimensional array similar to the previous one (chessboard, map, etc.)

  2. Save the sparse array, and you can restore the original number of two-dimensional arrays

  3. Overall thinking analysis

  1. code implementation

    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 chessArray1[][] = new int[11][11];
            chessArray1[1][2] = 1;
            chessArray1[2][3] = 2;
            chessArray1[4][5] = 2;
    
            // Output the original two-dimensional array
            System.out.println("Original 2D array:");
            for (int row[] :
                    chessArray1) {
                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
            int sum = 0;
            for (int i = 0; i < 11; i++) {
                for (int j = 0; j < 11; j++) {
                    if (chessArray1[i][j] != 0) {
                        sum++;
                    }
                }
            }
    
            // 2. Create the corresponding sparse array
            int sparseArray[][] = new int[sum+1][3];
    
            // Assign values to sparse arrays
            sparseArray[0][0] = 11;
            sparseArray[0][1] = 11;
            sparseArray[0][2] = sum;
    
            // Traverse the two-dimensional array and store non-0 values in sparseArr
            int cnt = 0;
            for (int i = 0; i < 11; i++) {
                for (int j = 0; j < 11; j++) {
                    if (chessArray1[i][j] != 0) {
                        cnt++;
                        sparseArray[cnt][0] = i;
                        sparseArray[cnt][1] = j;
                        sparseArray[cnt][2] = chessArray1[i][j];
                    }
                }
            }
    
            // Output sparse array form
            System.out.println("The sparse array is as follows:");
            for (int row[] : sparseArray) {
                for (int data : row) {
                    System.out.printf("%d\t", data);
                }
                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] above
             2. After reading a few rows of data from the sparse array, assign it to the original two-dimensional array */
            int chessArray2[][] = new int[sparseArray[0][0]][sparseArray[0][1]];
            for (int i = 1; i <= sparseArray[0][2]; i++) {
                chessArray2[sparseArray[i][0]][sparseArray[i][1]] = sparseArray[i][2];
            }
            
    
            // Output recovered 2D array
            System.out.println("Restored 2D array:");
            for (int row[] :
                    chessArray2) {
                for (int data :
                        row) {
                    System.out.printf("%d\t", data);
                }
                System.out.println();
            }
        }
    
    }
    

After class practice

requirement:

  1. Based on the above, save the sparse array to disk, such as map.data

  2. When restoring the original array, read map.data to restore

queue

A usage scenario of queue

Cases of Bank Queuing:

Queue introduction

  1. Queue is a sequential list, which can be implemented by array or linked list.

  2. Follow the principle of first in, first out. That is, the data stored in the queue should be taken out first. After the deposit, it shall be taken out

  3. Schematic: (use array to simulate queue schematic)

Array simulation queue idea

  • 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 shown in the figure below, where maxSize is the maximum capacity of the queue.

  • Because the output and input of the queue are processed from the front and rear ends respectively, two variables front and rear are required to record the subscripts at the front and rear ends of the queue respectively. The front will change with the data output, while the rear will change with the data input, as shown in the figure:

  • When we store data in the queue, it is called "addQueue". The processing of addQueue needs two steps: train of thought analysis

    1. Move the tail pointer backward: rear+1, when front == rear [empty]
    2. If the tail pointer rear is less than the maximum subscript maxSize-1 of the queue, the data will be stored in the array element referred to by rear, otherwise the data cannot be stored.
    3. rear == maxSize - 1 [queue full]

code implementation

package com.atguigu.queue;

import java.util.Scanner;

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");
         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~~");
   }

}

// 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 = 0; i < arr.length; i++) {
         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];
   }
}

Problem analysis and optimization

  1. At present, the array cannot be used once, which does not achieve the effect of reuse

  2. Use the algorithm to improve this array into a ring queue module

Array simulation ring queue

The previous array simulates the optimization of the queue and makes full use of the array. Therefore, the array is regarded as a ring. (it can be realized by taking mold)

Analysis description:

  1. When the next index in the tail index is the header index, it indicates that the queue is full, that is, one queue capacity is vacated as a convention. This should be noted when judging that the queue is full

    (rear + 1)% maxsize = = front full]

  2. rear == front [empty]

  3. Schematic diagram of analysis:

code implementation

package com.atguigu.queue;

import java.util.Scanner;

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");
         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~~");
   }

}


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];
   }
}

Tags: Java Algorithm data structure

Posted on Thu, 30 Sep 2021 22:59:24 -0400 by jnmunsey