Data Structures and Algorithms: Detailed Explanation of Sparse Arrays and Queues (with LeetCode related hot topics)


foreword

The notes are organized in: [Silicon Valley] Data Structure and Algorithm (Java Data Structure and Algorithm)

Overview of Data Structures and Algorithms

The relationship between data structures and algorithms

  • Data structure (data structure) is a subject that studies the way of organizing data. With a programming language, there is also a data structure. Learning the data structure well can write more beautiful and efficient code.
  • To learn the data structure well, we must think more about how to solve the problems encountered in life with programs.
  • Program = data structure + algorithm
  • The data structure is the basis of the algorithm . In other words, if you want to learn the algorithm well, you need to learn the data structure in place.

Several problems encountered in actual programming

Problem 1: String replacement problem

1674225902672

Summary : need to use singly linked list data structure

Question 2: Backgammon program problem

1674226019082

How to judge the winning or losing of the game, and can complete the function of saving and exiting and continuing the game

  • Chessboard Two-dimensional array => ( sparse array ) -> write to file [archive function]

  • Read file->sparse array->two-dimensional array->chessboard [continued from last game]

Question 3: Joseph (Josephu) problem (throwing handkerchief problem)

  1. Josephu's problem is : Let n people numbered 1, 2, ... n sit in a circle, agree that the person numbered k (1<=k<=n) will start counting from 1, and the person who counts to m will go out , its next person starts counting from 1, and the person who counts to m goes out of the queue again, and so on, until everyone goes out of the queue, thus generating a sequence of queue numbers.

  2. Tip : Use a circular linked list without a head node to deal with the Josephu problem: first form a single circular linked list (one-way circular linked list) with n nodes, and then start counting from 1 from k nodes until m , the corresponding node is deleted from the linked list, and then counting from the next node of the deleted node starts from 1, until the last node is deleted from the linked list and the algorithm ends.

  3. Summary : To complete the Joseph problem, you need to use the data structure of the one-way circular linked list

Other Common Algorithmic Questions

1674226271409

  • Road repair problem => minimum spanning tree (weighted value) [data structure] + Prim's algorithm

  • Shortest Path Problem => Graph + Floyd Algorithm

  • Tower of Hanoi => branching algorithm

  • Eight Queens Problem => Backtracking

Linear and Nonlinear Structures

Data structures include : linear structures and nonlinear structures.

linear structure

  • As the most commonly used data structure, the linear structure is characterized by a one-to- one linear relationship between data elements

  • There are two different storage structures for linear structures, namely sequential storage structures ( arrays ) and linked storage structures (linked lists) . A sequentially stored linear table is called a sequential table, and the storage elements in the sequential table are continuous

  • The linear list of linked storage is called linked list. The storage elements in the linked list are not necessarily continuous . The element nodes store the address information of data elements and adjacent elements.

  • Common linear structures are: arrays, queues, linked lists, and stacks

nonlinear structure

Non-linear structures include : two-dimensional arrays, multidimensional arrays, generalized tables, tree structures, graph structures

Sparse Arrays and Queues

Sparse sparsearray array

look at an actual need

In the backgammon program written, there are functions of saving, exiting and reloading.

analyse problem:

1674399037591

Because many values ​​of the two-dimensional array are the default value 0, so a lot of meaningless data is recorded .-> Sparse array .

basic introduction

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

The processing method of sparse array is:

  • How many rows and columns are there in the record array , and how many different values ​​are there?

  • Record the rows, columns and values ​​of elements with different values ​​in a small-scale array, thereby reducing the size of the program

Sparse array example

1674399181984

Applications

  1. Use sparse arrays, to keep 2D arrays like the previous ones (chessboards, maps, etc.)

  2. Save the sparse array and restore the original two-dimensional array

  3. Overall thinking analysis

    1674399302273

  4. Code

    package com.atguigu.sparsearray;
    
    @SuppressWarnings("all")
    public class SparseArray {
          
          
    
        public static void main(String[] args){
          
          
            //创建一个原始的二维数组
            //0:表示没有棋子  1 表示 黑子 ,2 表示 蓝子
            int chessArr[][] = new int[11][11];
            chessArr[1][2] = 1;
            chessArr[2][3] = 2;
            System.out.println("原始的二维数组:");
            for (int[] row : chessArr) {
          
          
                for (int data : row) {
          
          
                    System.out.printf("%d\t",data);
                }
                System.out.println();
            }
    
            //将二维数组转为稀疏数组
            //1. 先遍历二维数组,得到非0数据的个数
            int sum = 0;
            int length = chessArr.length;
            for (int i = 0; i <length; i++) {
          
          
                for (int j = 0; j < chessArr[i].length; j++) {
          
          
                    if (chessArr[i][j] != 0){
          
          
                        sum++;
                    }
                }
            }
            //System.out.println("sum = "+sum);
    
            //2. 创建对应的稀疏数组
            int sparseArr[][] = new int[sum+1][3];
            //给稀疏数组赋值
            sparseArr[0][0] = 11;
            sparseArr[0][1] = 11;
            sparseArr[0][2] = sum;
    
            //count 用于记录是第几个非 0 数据
            int count = 0;
            for (int i = 0; i < chessArr.length; i++) {
          
          
                for (int j = 0; j < chessArr[i].length; j++) {
          
          
                    if (chessArr[i][j] != 0){
          
          
                        count++;
                        sparseArr[count][0] = i;
                        sparseArr[count][1] = j;
                        sparseArr[count][2] = chessArr[i][j];
    //                    sparseArr[?][0] = i;
    //                    sparseArr[?][1] = j;
    //                    sparseArr[?][2] = chessArr[i][j];
                    }
                }
            }
            //3. 输出稀疏数组
            System.out.println();
            System.out.println("得到的稀疏数组为:");
            for (int i = 0; i < sparseArr.length; i++) {
          
          
                System.out.printf("%d\t%d\t%d\t\n",sparseArr[i][0],sparseArr[i][1],sparseArr[i][2]);
            }
    
            int chessArr2[][] = new int[sparseArr[0][0]][sparseArr[0][1]];
            for (int i = 1; i < sparseArr.length; i++) {
          
          
                chessArr2[sparseArr[i][0]][sparseArr[i][1]] = sparseArr[i][2];
            }
    
            System.out.println();
            System.out.println("恢复后的二维数组:");
    //        for (int i = 0; i < chessArr2.length; i++) {
          
          
    //            for (int j = 0; j < chessArr2[i].length; j++) {
          
          
    //                System.out.printf("%d\t",chessArr2[i][j]);
    //            }
    //            System.out.println();
    //        }
            for (int[] row :chessArr2) {
          
          
                for (int dtat : row) {
          
          
                    System.out.printf("%d\t",dtat);
                }
                System.out.println();
            }
    
        }
    }
    

Homework

Requirements :

  • On the previous basis, save the sparse array to disk, such as map.data

  • When restoring the original array, read map.data for restoration

Analysis :

You only need to add two methods on the original basis:

  • saveSparseArrToFile(sparseArr, filePath): save the sparse array to a local file
  • getSparseArrFromFile(filePath): Read the file and convert the read sparse array into a two-dimensional array

Common method

Code implementation :

    public static void saveSparseArrToFile(int[][] sparse, String filePath) throws IOException {
    
    
        //写入文件
        FileOutputStream fos = null;
        DataOutputStream dos = null;
        try {
    
    
            fos = new FileOutputStream(new File(filePath));
            dos = new DataOutputStream(fos);
            for (int[] row : sparse) {
    
    
                for (int data : row) {
    
    
                    dos.writeInt(data);
                }
            }
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            if (dos != null) {
    
    
                dos.close();
            }

            if (fos != null) {
    
    
                fos.close();
            }
        }
    }

    public static int[][] getSparseArrFromFile(String filePath) throws IOException {
    
    
        int[][] arr = {
    
    };

        FileInputStream fis = null;
        DataInputStream dis = null;

        try {
    
    
            fis = new FileInputStream(new File(filePath));
            dis = new DataInputStream(fis);

            //读取数据
            int row = dis.readInt();
            int column = dis.readInt();
            int count = dis.readInt();
            //稀疏数组第一行有三个数字 分别代表原数组的 有几行  有几列  有多少个非空数据
            arr = new int[row][column];
            //根据count 给 arr赋值
            for (int i = 0; i < count; i++) {
    
    
                arr[dis.readInt()][dis.readInt()] = dis.readInt();
            }
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            //关闭流
            if (dis != null) {
    
    
                dis.close();
            }
            if (fis != null) {
    
    
                fis.close();
            }
        }
        return arr;
    }

Recommended reading article : Analysis of DataInputStream and DataOutputStream of Java IO Stream

only for sparse arrays

Code implementation :

public static void saveSparseArrToFile(int[][] sparse, String filePath) throws IOException {
    
    
        //写入文件
        FileOutputStream fos = null;

        try {
    
    
            fos = new FileOutputStream(filePath);
            for (int i = 0; i < sparse.length; i++) {
    
    
                StringBuffer stringBuffer = new StringBuffer();
                stringBuffer.append(sparse[i][0] + "\t" + sparse[i][1] + "\t" + sparse[i][2] + "\n");
                //System.out.println(stringBuffer);
                fos.write(stringBuffer.toString().getBytes("utf-8"));
            }
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            fos.close();
        }
    }

    public static int[][] getSparseArrFromFile(String filePath) throws IOException {
    
    

        int[][] arr = null;
        FileReader fileReader = null;
        BufferedReader bufferedReader = null;

        try {
    
    
            fileReader = new FileReader(filePath);
            bufferedReader = new BufferedReader(fileReader);
            String line = null;
            int countSparse = 0;
            int number = 0;

            while ((line = bufferedReader.readLine()) != null) {
    
    
                //System.out.println(line);
                // 将每一行转为数组
                String[] split = line.split("\t");
                Integer row = Integer.valueOf(split[0].trim());
                Integer col = Integer.valueOf(split[1].trim());
                Integer value = Integer.valueOf(split[2].trim());
                if (countSparse == 0) {
    
    
                    arr = new int[row][col];
                } else {
    
    
                    number++;
                    arr[row][col] = value;
                }
                countSparse++;
            }

        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            bufferedReader.close();
            fileReader.close();
        }
        return arr;
    }
}

The basic code is as follows (choose one of the above two methods)

package com.atguigu.sparsearray;

import java.io.*;

@SuppressWarnings("all")
public class SparseArrayIO {
    
    

    public static void main(String[] args) throws IOException {
    
    

        //1. 创建一个原始的二维数组
        int chessArr[][] = new int[11][11];
        chessArr[1][2] = 1;
        chessArr[2][3] = 2;
        System.out.println("原始的二维数组:");
        for (int[] ints : chessArr) {
    
    
            for (int i : ints) {
    
    
                System.out.printf("%d\t", i);
            }
            System.out.println();
        }

        //2. 遍历二维数组,得到二维数组非 0 数据的个数
        int count = nums(chessArr);

        //3. 将二维数组转化为稀疏数组
        int index = 1;
        int sparseArr[][] = new int[count + 1][3];

        //稀疏数组 第 1 行
        sparseArr[0][0] = chessArr.length;
        sparseArr[0][1] = 11;
        sparseArr[0][2] = count;

        //稀疏数组 第二行及以后
        for (int i = 0; i < chessArr.length; i++) {
    
    
            for (int j = 0; j < chessArr[i].length; j++) {
    
    
                if (chessArr[i][j] != 0) {
    
    
                    sparseArr[index][0] = i;
                    sparseArr[index][1] = j;
                    sparseArr[index][2] = chessArr[i][j];
                    index++;
                }
            }
        }

        //打印稀疏数组
        System.out.println("转换后的稀疏数组:\n----------------------------");
        printNums(sparseArr);
        
        //4.将稀疏数组保存到文件中
        String filePath = "E:\\myTemp\\123.txt";
        saveSparseArrToFile(sparseArr, filePath);

        //5.将文件数据读取到稀疏数组中
        int[][] fileSparseArr = getSparseArrFromFile(filePath);
        //打印读取的稀疏数组
        System.out.println("打印读取转换后的二维数组:\n----------------------------");
        printNums(fileSparseArr);
    }

    public static int nums(int[][] num) {
    
    
        int count = 0;
        for (int i = 0; i < num.length; i++) {
    
    
            for (int j = 0; j < num[i].length; j++) {
    
    
                if (num[i][j] != 0) {
    
    
                    count++;
                }
            }
        }
        return count;
    }


    public static void printNums(int[][] nums) {
    
    
        for (int[] ints : nums) {
    
    
            for (int i : ints) {
    
    
                System.out.printf("%d\t", i);
            }
            System.out.println();
        }
    }

queue

A usage scenario for queues

Example of bank queuing:

1674399502538

queue introduction

  1. A queue is an ordered list that can be implemented as an array or a linked list .

  2. Follow the principle of first in first out . That is: the data stored in the queue first must be taken out first. What is deposited later must be withdrawn

  3. Schematic diagram: (Schematic diagram of queue simulation using array)

1674399592978

Array simulation queue idea

  • The queue itself is an ordered list. 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 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 of the front and rear ends of the queue respectively. The front will change with the data output, and the rear will change with the data input. as the picture shows:

    1674399739539

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

    • Move the tail pointer backward: rear+1, when front == rear 【empty】

    • If the tail pointer rear is smaller than the maximum subscript maxSize-1 of the queue, the data will be stored in the array element pointed to by rear, otherwise the data cannot be stored. rear == maxSize - 1[queue full]

  • Code

  package com.atguigu.queue;

import java.util.Scanner;

public class ArrayQueueDemo {
    
    

    public static void main(String[] args) {
    
    

        //测试
        //创建一个队列
        ArrayQueue arrayQueue = new ArrayQueue(3);
        char key = ' '; //接受用户输入
        Scanner scanner = new Scanner(System.in);
        boolean loop = true;

        //输出一个菜单
        while(loop){
    
    
            System.out.println("---------数组模拟队列--------");
            System.out.println("s(show): 显示队列");
            System.out.println("e(exit): 退出程序");
            System.out.println("a(add): 添加数据到队列");
            System.out.println("g(get): 从队列取出数据");
            System.out.println("h(head): 查看队列头的数据");
            System.out.println("--------------------------");

            key = scanner.next().charAt(0);     //接收一个字符
            switch (key){
    
    
                case 's':
                    arrayQueue.showQueue();
                    break;
                case 'a':
                    System.out.println("清输入要添加的数:");
                    int value = scanner.nextInt();
                    arrayQueue.addQueue(value);
                    break;
                case 'g':
                    try {
    
    
                        int res = arrayQueue.getQueue();
                        System.out.printf("取出的数据是:%d\n",res);
                    } catch (Exception e) {
    
    
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'h':
                    try {
    
    
                        int head = arrayQueue.headQueue();
                        System.out.printf("队列头为:%d\n",head);
                    }catch(Exception e){
    
    
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'e':
                    scanner.close();
                    loop = false;
                    break;
                default:
                    break;
            }

        }
        System.out.println("---------退出程序----------");

    }

}

// 使用数组模拟队列

//编写一个 ArrayQueue类
class ArrayQueue{
    
    

    //数组最大容量
    private int maxSize;

    //队列头
    private int front;

    //队列尾
    private int rear;

    //该数组用于存放数据,模拟队列
    private int[] arr;

    //创造队列的构造器
    public ArrayQueue(int arrMaxSize){
    
    
        maxSize = arrMaxSize;
        arr = new int[maxSize];
        front = -1;  //指向队列头部,分析书 front 是 指向队列头的前一个位置
        rear = -1;  //指向队列尾,指向队列尾的数据(队列最后一个数据)
    }

    //判断队列是否满
    public boolean isFull(){
    
    
        return rear == maxSize-1;
    }

    //判断队列是否为空
    public boolean isEmpty(){
    
    
        return front == rear;
    }

    //添加数据到队列
    public void addQueue(int n){
    
    

        //判断队列是否满
        if (isFull()){
    
    
            System.out.println("队列满,不能添加数据!");
            return;
        }

        rear++;     //让 rear 后移
        arr[rear] = n;
    }

    //获取队列的数据,出队列
    public int getQueue(){
    
    

        //判断队列是否为空
        if (isEmpty()){
    
    
            //通过异常抛出
            throw new RuntimeException("对列空,不能获取数据!");
        }

        front++;        //front后移
        return arr[front];
    }

    //显示队列所有数据
    public void showQueue(){
    
    
        //遍历
        if (isEmpty()){
    
    
            System.out.println("队列空,没有数据!");
            return;
        }
//		这里老师写的有点问题,详见分析
//        for (int i = 0; i < arr.length; i++) {
    
    
//            System.out.printf("arr[%d] = %d\n",i,arr[i]);
//        }
        for (int i = front + 1; i <= rear; i++) {
    
    
            System.out.printf("arr[%d] = %d\n",i,arr[i]);
        }
    }

    //显示队列定头数据
    public int headQueue(){
    
    
        //判断
        if (isEmpty()){
    
    
            throw new RuntimeException("队列空的,没有数据~");
        }
        return arr[front+1];
    }

}
  • problem analysis and optimization

  • At present, the array cannot be used after being used once, and the effect of multiplexing has not been achieved.

    • Use the algorithm to improve this array into a circular queue Modulo: %

Arrays emulate circular queues

The optimization of the previous array simulation queue makes full use of the array. Therefore, the array is regarded as a ring. ( It can be realized by taking a modulus )

Analysis Description:

  1. When the next one of the tail index is the head index, it means that the queue is full, and the queue capacity is about to be vacated as a promise. This needs to be paid attention to when judging that the queue is full (rear + 1) % maxSize == front full]

  2. rear == front [empty]

  3. Analysis diagram:

    1674400099382

  4. Code

    package com.atguigu.queue;
    
    import java.util.Scanner;
    
    public class CircleArrayQueueDemo {
          
          
        public static void main(String[] args) {
          
          
    
            //测试一把
            System.out.println("测试数组模拟环形队列的案例~~~");
            // 创建一个环形队列
            CircleArray arrayQueue = new CircleArray(4); //说明设置 4, 其队列的有效数据最大是 3
            char key = ' '; // 接收用户输入
            Scanner scanner = new Scanner(System.in);//
            boolean loop = true;
            // 输出一个菜单
            while(loop){
          
          
                System.out.println("-------数组模拟环形队列------");
                System.out.println("s(show): 显示队列");
                System.out.println("e(exit): 退出程序");
                System.out.println("a(add): 添加数据到队列");
                System.out.println("g(get): 从队列取出数据");
                System.out.println("h(head): 查看队列头的数据");
                System.out.println("--------------------------");
    
                key = scanner.next().charAt(0);     //接收一个字符
                switch (key){
          
          
                    case 's':
                        arrayQueue.showQueue();
                        break;
                    case 'a':
                        System.out.println("清输入要添加的数:");
                        int value = scanner.nextInt();
                        arrayQueue.addQueue(value);
                        break;
                    case 'g':
                        try {
          
          
                            int res = arrayQueue.getQueue();
                            System.out.printf("取出的数据是:%d\n",res);
                        } catch (Exception e) {
          
          
                            System.out.println(e.getMessage());
                        }
                        break;
                    case 'h':
                        try {
          
          
                            int head = arrayQueue.headQueue();
                            System.out.printf("队列头为:%d\n",head);
                        }catch(Exception e){
          
          
                            System.out.println(e.getMessage());
                        }
                        break;
                    case 'e':
                        scanner.close();
                        loop = false;
                        break;
                    default:
                        break;
                }
    
            }
            System.out.println("---------退出程序----------");
    
        }
    }
    
    class CircleArray{
          
          
        //数组最大容量
        private int maxSize;
    
        //变量的含义做一个调整: front 就指向队列的第一个元素, 也就是说 arr[front] 就是队列的第一个元素
        //front 的初始值 = 0
        private int front;
    
        //变量的含义做一个调整:rear 指向队列的最后一个元素的后一个位置. 因为希望空出一个空间做为约定
        //rear 的初始值 = 0
        private int rear;
    
        //该数组用于存放数据,模拟队列
        private int[] arr;
    
        public CircleArray(int arrMaxSize){
          
          
            maxSize = arrMaxSize;
            arr = new int[maxSize];
    //        front = 0;
    //        rear = 0
        }
    
        //判断队列是否满
        public boolean isFull(){
          
          
            return (rear + 1) % maxSize == front;
        }
    
        //判断是否为空
        public boolean isEmpty(){
          
          
            return rear == front;
        }
    
        //添加数据到队列
        public void addQueue(int n){
          
          
            //判断队列是否满
            if (isFull()){
          
          
                System.out.println("队列满,不能加入数据~");
                return;
            }
            //直接将数据加入
            arr[rear] = n;
            //将 rear 后移,这里必须考虑取模
            rear = (rear + 1) % maxSize;
        }
    
        //获取队列的数据,出队列
        public int getQueue(){
          
          
            //判断队列是否为空
            if (isEmpty()){
          
          
                // 通过抛出异常
                throw new RuntimeException("队列空,不能取数据");
            }
            // 这里需要分析出 front 是指向队列的第一个元素
            // 1. 先把 front 对应的值保留到一个临时变量
            // 2. 将 front 后移, 考虑取模
            // 3. 将临时保存的变量返回
            int value = arr[front];
            front = (front + 1)% maxSize;
            return value;
        }
    
        //显示队列的所有数据
        public void showQueue(){
          
          
            //遍历
            if (isEmpty()){
          
          
                System.out.println("队列空的,没有数据~~");
                return;
            }
            // 思路:从 front 开始遍历,遍历多少个元素
            // 动脑筋
            for (int i = front; i < front+size(); i++) {
          
          
                System.out.printf("arr[%d] = %d\n",i%maxSize,arr[i%maxSize]);
            }
        }
    
        //求出当前队列有效数据个数
        public int size(){
          
          
            //rear = 2
            //front = 1
            //maxSize = 3
            return (rear + maxSize - front) % maxSize;
        }
    
        // 显示队列的头数据, 注意不是取出数据
        public int headQueue(){
          
          
            // 判断
            if (isEmpty()) {
          
          
                throw new RuntimeException("队列空的,没有数据~~");
            }
            return arr[front];
        }
    }
    

analyze

array analog queue

problem solved

  1. Only add one data: 10, enter s and press Enter to find a total of 3 elements, but the other elements are 0

    1674476135565

  2. After taking out the data, press s to enter and check the queue and find that it is still there. Although the h check queue head data has been changed to 20, it feels inappropriate

    1674476405311

  3. Modify the showQueue() method

    First look at the definition:

            front = -1;  //指向队列头部,分析书 front 是 指向队列头的前一个位置
            rear = -1;  //指向队列尾,指向队列尾的数据(队列最后一个数据)
    

    In the for loop here, i is changed to front + 1 (essentially still 0), and the length becomes i <= rear

    rear points to the last element at the end of the queue, so the queue data is from front to rear (including itself)

        //显示队列所有数据
        public void showQueue(){
          
          
            //遍历
            if (isEmpty()){
          
          
                System.out.println("队列空,没有数据!");
                return;
            }
    
    //        for (int i = 0; i < arr.length; i++) {
          
          
    //            System.out.printf("arr[%d] = %d\n",i,arr[i]);
    //        }
            for (int i = front + 1; i <= rear; i++) {
          
          
                System.out.printf("arr[%d] = %d\n",i,arr[i]);
            }
        }
    
  4. test

    View after adding data to the queue:

    1674476872846

    View after fetching data from the queue:

    1674476978137

    Test success!

Arrays emulate circular queues

prerequisite

First understand: % operator

x % y = z, no matter how x changes (increment, etc.) z must be 0 to y-1 (loop, etc.), it is amazing, this is the subtlety of the algorithm! ! !

    //数组最大容量
    private int maxSize;

    //变量的含义做一个调整: front 就指向队列的第一个元素, 也就是说 arr[front] 就是队列的第一个元素
    //front 的初始值 = 0
    private int front;

    //变量的含义做一个调整:rear 指向队列的最后一个元素的后一个位置. 因为希望空出一个空间做为约定
    //rear 的初始值 = 0
    private int rear;

    //该数组用于存放数据,模拟队列
    private int[] arr;

How to tell if the queue is full/empty?

code :

    //判断队列是否满
    public boolean isFull(){
    
    
        return (rear + 1) % maxSize == front;
    }
	//判断是否为空
    public boolean isEmpty(){
    
    
        return rear == front;
    }

Recommended reading article : Circular queue: 3 ways to judge whether the queue is empty or full

Queue full condition: (rear + 1) % maxSize == front

From the meaning of the rear variable: rear = maxsize - 1, when the queue is full, the last position is actually empty and no data is stored, so rear + 1 = maxsize, taking maxSize = 4 in the code as an example, when the queue is full, The last data position is 2 (0,1,2,3), rear = 2+1=3, front = 0, set the formula: (3+1)% 4 == 0

The condition for the queue to be empty: rear == front

When the front and rear pointers of the queue coincide, it indicates that there is no data in the queue

How to add data to the queue?

code :

    public void addQueue(int n){
    
    
        //判断队列是否满
        if (isFull()){
    
    
            System.out.println("队列满,不能加入数据~");
            return;
        }
        //直接将数据加入
        arr[rear] = n;
        //将 rear 后移,这里必须考虑取模
        rear = (rear + 1) % maxSize;
    }

Analysis :

When the queue is not full, directly assign the data to arr[rear], and then move rear one bit backward. rear moves back, cannot directly rear ++. Because it is a circular queue, there will be an array subscript out of bounds exception, or take maxsize = 4 as an example: when arr[2], arr[3] store data in the queue, (arr[0], arr[1] are empty ), add the data storage location again: arr[0]

Assign the parameter n to the position of the rear in the array arr. Since the rear refers to the last bit of the rear in the circular queue, there is no need to consider the problem of the array arr[0]. At this time, the position of the rear will be determined by (rear+1)%maxSize In the past, since the rear itself has a +1 attribute, the "1" in the expression is prepared for the data to be added, and the +1 of the rear itself is prepared for a space

How to get the data of the queue and get out of the queue?

code :

    public int getQueue(){
    
    
        //判断队列是否为空
        if (isEmpty()){
    
    
            // 通过抛出异常
            throw new RuntimeException("队列空,不能取数据");
        }
        // 这里需要分析出 front 是指向队列的第一个元素
        // 1. 先把 front 对应的值保留到一个临时变量
        // 2. 将 front 后移, 考虑取模
        // 3. 将临时保存的变量返回
        int value = arr[front];
        front = (front + 1)% maxSize;
        return value;
    }

Analysis :

If it is not empty, define a variable value as the value retrieved by the user, and assign *arr[front]* to value, and use it as the value retrieved. Since the front has its own +1 attribute (definition), there is no need to consider the characteristics of the array itself.
The front is shifted one bit to leave a space, which conforms to the agreement of the circular queue. It is used to take the modulus of the maximum capacity of the array maxSize, and it is obtained at this time The position where the front of the ring queue should be, and the final return value

How to display all data of the queue?

code :

    public void showQueue(){
    
    
        //遍历
        if (isEmpty()){
    
    
            System.out.println("队列空的,没有数据~~");
            return;
        }
        // 思路:从 front 开始遍历,遍历多少个元素
        // 动脑筋
        for (int i = front; i < front+size(); i++) {
    
    
            System.out.printf("arr[%d] = %d\n",i%maxSize,arr[i%maxSize]);
        }
    }

Analysis :

arr[%d] can be usediThe value at the time of self-increment is used to take the modulus of the ring queue to obtain the actual position of the array, and at the same time lock the value through the arr array

How to calculate the number of valid data in the current queue?

code :

    public int size(){
    
    
        //rear = 2
        //front = 1
        //maxSize = 3
        return (rear + maxSize - front) % maxSize;
    }

Recommended reading article : Array implements circular queue - get the number of valid data

How to display the head data of the queue, pay attention not to take out the data?

code :

    public int headQueue(){
    
    
        // 判断
        if (isEmpty()) {
    
    
            throw new RuntimeException("队列空的,没有数据~~");
        }
        return arr[front];
    }

Apply what you have learned

LeetCode array related topics

LeetCode queue related topics

Data Structure and Algorithm Series Articles: Continuously Updating! ! !

Guess you like

Origin blog.csdn.net/Htupc/article/details/129250665