[java] - Algorithms and Data Structures - Chapter 3 - Queues

3. Queue

1 Introduction

  1. A queue is an ordered list, which can be implemented by an array or a linked list
  2. Follow the principle of first in first out.
  3. As shown in the figure below: when saving data, the front remains unchanged, and the rear changes; when fetching data, the rear position remains unchanged, and the front position changes

2. Icon

Found in the picture site[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-hwV4khKf-1649303240655)(https://secure2.wostatic.cn/static/nQwtdspuVpA6vWQBFmA1Aa/image.png)]

  • rear: the tail of the queue
  • front: the head of the data

3. Array implements queue

the code

package 二__队列;

/*
队列
场景:排队
介绍:先进先出



*/

import java.util.Queue;

public class Test {
    
    

    public static void main(String[] args) {
    
    
            test1();
    }

    // 数组队列模型
    public static void test1() {
    
    
        ArrayQueue arrayQueue = new ArrayQueue(10);
        arrayQueue.add(1);
        arrayQueue.add(2);
        arrayQueue.add(3);
        arrayQueue.add(4);
        arrayQueue.add(5);
        arrayQueue.add(6);
        arrayQueue.add(7);
        arrayQueue.add(8);
        arrayQueue.add(9);
        arrayQueue.add(10);
        arrayQueue.add(11);
        arrayQueue.showQueue();
        System.out.println("头部数据:"+arrayQueue.headQueue());
    }
}

// 数组队列
class ArrayQueue {
    
    
    private int maxSize;  // 最大容量
    private int front;  // 队列头
    private int rear;  // 队列尾
    private int[] arr; // 用来存储数据

    // 创建队列的构造器
    public ArrayQueue(int maxSize) {
    
    
        this.maxSize = maxSize;
        this.arr = new int[maxSize];
        this.front = -1;  // 指向队列头的前一个位置
        this.rear = -1;
    }

    public boolean isFull() {
    
    
        return rear == maxSize - 1;
    }

    public boolean isEmpty() {
    
    
        return front == rear;
    }

    // 添加
    public void add(int n) {
    
    
        // 判断是否满
        if (isFull()) {
    
    
            System.out.println("队列满,不可以添加数据");
            return;
        }
        // 尾部后移一位
        rear++;
        arr[rear] = n;
    }

    // 获取
    public int poll() {
    
    
        // 返回头部第一个
        if (isEmpty()) {
    
    
            System.out.println("队列为空");
            return -1;
        }
        front++;
        return arr[front];
    }

    //显示所有数据
    public void showQueue(){
    
    
        if(isEmpty()){
    
    
            System.out.println("队列为空");
            return;
        }
        for (int i : arr) {
    
    
            if(i != 0) System.out.println(i);
        }
    }

    // 显示队列头数据
    public int headQueue(){
    
    
        if(isEmpty()){
    
    
            System.out.println("队列为空");
            return -1;
        }
        return arr[front+1];
    }
}

Review code

/*
    队列基本要求:
    1. 先进先出
    2. rear 表示尾部
    3. front 表示头部
    4. array 表示存储数据的数组

    1. 每添加一个数据 rear+1;
    2. 每取出一个数据 front+1;
*/

// 数组队列
@Data
class TestArrayQueue{
    
    
    private int maxSize;
    private int rear ;
    private int front ;
    private int[] array;

    public TestArrayQueue(int  size){
    
    
        this.maxSize = size;
        array = new int[maxSize];
        rear = -1;
        front = -1;
    }

    // 判断是否已满
    public boolean isFull(){
    
    
        return rear-front == maxSize;

    }
    // 判断是否为空
    public boolean isEmpty(){
    
    
        return rear == front;
    }
    // 存储数据
    public void add(int value){
    
    
        if(isFull()){
    
    
            throw new RuntimeException("队列已满");
        }
        rear ++;
        array[rear] = value;
    }

    // 取出数据
    public int get(){
    
    
        if(isEmpty()){
    
    
            throw new RuntimeException("队列为空");
        }
        front ++;
        int value = array[front];
        array[front] = 0;
        return value;
    }

    // 打印所有数据
    public void printAll(){
    
    
        System.out.println(Arrays.toString(array));
    }
}
    // 测试 数组队列
    public static void testArrayQueue(){
    
    
        TestArrayQueue testArrayQueue = new TestArrayQueue(5);
        Scanner scanner = new Scanner(System.in);
        while (true){
    
    
            System.out.println("-------------------------------------");
            System.out.println("1) 添加数据");
            System.out.println("2) 获取数据");
            System.out.println("3) 打印所有数据");
            String s = scanner.nextLine();
            switch (s){
    
    
                case "1":{
    
    
                    System.out.print("输入数据:___");
                    int i = scanner.nextInt();
                    testArrayQueue.add(i);
                    System.out.println("输入成功");
                    System.out.println("---------------");
                    continue;
                }
                case "2":{
    
    
                    System.out.println(testArrayQueue.get());
                    continue;
                }
                case "3":{
    
    
                    testArrayQueue.printAll();
                    continue;
                }
            }
        }
    }

4. Arrays simulate ring queues

  1. question

    Arrays cannot be reused, one-time

    Use algorithm optimization to improve into a ring queue, use modulo algorithm to optimize

  2. analyze

    • front now points to the first element of the queue (was pointing to the previous element)

    • rear meaning adjustment: rear points to the position after the last element of the queue. Make a space to make a promise.

      It is convenient to judge whether front and rear are equal: the initial value of rear is 0.

    • When the queue is full, the condition is (rear+1)%maxSize = front【full】

    • When the queue is empty, rear == front(0) [empty]

    [External link picture transfer failed, the source site may have an anti-theft link mechanism, it is recommended to save the picture and upload it directly (img-I7SmWrMv-1649303240655)(https://secure2.wostatic.cn/static/fJFKyJNbjkHu2XfzmjGJHf/image.png)]

  3. the code

the code

package 二__队列;
/*
    Date:2022/4/6
    author: Blue Friday
    describe: //todo
*/


public class Test2 {
    
    
    public static void main(String[] args) {
    
    
        CircleArrayQueue circleArrayQueue = new CircleArrayQueue(4);
        circleArrayQueue.add(1);
        circleArrayQueue.add(2);
        circleArrayQueue.add(3);
        circleArrayQueue.add(4);
        System.out.println(circleArrayQueue.poll());
        System.out.println(circleArrayQueue.poll());
        System.out.println(circleArrayQueue.poll());
        System.out.println(circleArrayQueue.poll());
//        System.out.println(circleArrayQueue.poll());
        circleArrayQueue.add(60);
        System.out.println(circleArrayQueue.poll());

    }
}

// 环形队列
class CircleArrayQueue {
    
    
    private int maxSize;  // 最大容量
    private int front;  // 队列头
    private int rear;  // 队列尾
    private int[] arr; // 用来存储数据

    // 创建队列的构造器
    public CircleArrayQueue(int arrmaxSize) {
    
    
        maxSize = arrmaxSize +1;
        this.arr = new int[maxSize];
        this.front = 0;  // 指向队列头的前一个位置
        this.rear =  0;  // 指向队列尾
    }

    // 满队列条件
    public boolean isFull() {
    
    
        return (rear + 1 )%maxSize == front;
    }

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

    // 添加
    public void add(int n) {
    
    
        // 判断是否满
        if (isFull()) {
    
    
            System.out.println("队列满");
            return;
        }
        arr[rear] = n;
        // 将rear后移,这里需要取模,
        rear = (rear + 1)%maxSize;
    }

    // 获取
    public int poll() {
    
    
       if(isEmpty()){
    
    
           throw new RuntimeException("队列空");
       }
       int value = arr[front];
       front = (front +1) % maxSize;
       return value;
    }

    //显示所有数据
    public void showQueue() {
    
    
        if (isEmpty()) {
    
    
            System.out.println("队列为空");
            return;
        }
        // 遍历多少元素
        // 有效数据个数
        int size = size();
        for (int i = 0; i < front + size ; i++) {
    
    
            System.out.println(i % maxSize+": "+arr[i % maxSize]);

        }
    }

    // 显示队列头数据
    public int headQueue() {
    
    
        if (isEmpty()) {
    
    
            System.out.println("队列为空");
            return -1;
        }
        return arr[front];
    }
    // 队列有效个数
    public int size(){
    
    
        return (rear + maxSize - front)%maxSize;
    }
}

Review code

  // 测试环形数组
    public static void testCircularQueueC() {
    
    
        TestCircularQueue testCircularQueue = new TestCircularQueue(5);
        Scanner scanner = new Scanner(System.in);
        while (true) {
    
    
             try {
    
    
                 System.out.println("-------------------------------------");
                 System.out.println("1) 添加数据");
                 System.out.println("2) 获取数据");
                 System.out.println("3) 打印所有数据");
                 String s = scanner.nextLine();
                 switch (s) {
    
    
                     case "1": {
    
    
                         System.out.print("输入数据:___");
                         int i = scanner.nextInt();
                         testCircularQueue.add(i);
                         System.out.println("输入成功");
                         System.out.println("---------------");
                         continue;
                     }
                     case "2": {
    
    
                         System.out.println(testCircularQueue.get());
                         continue;
                     }
                     case "3": {
    
    
                         testCircularQueue.printArray();
                         continue;
                     }
                 }
             }catch (Exception e){
    
    
                 System.out.println(e.getMessage());
             }
        }
    }
// 环形数组队列
@Data
class TestCircularQueue {
    
    
    /*
        1. 修改定义 rear 初始  = 0; front = 0;
        2. 队列满:( rear + 1 )%maxSize = front;
        3. 队列空:rear == front
        举例:
        1. 不修改定义
            - 初始化数组(指向前一个元素): rear = -1 ;front = -1;maxSize = 3;
              队列满:rear - front == maxSize;
              队列空:rear == front
            - 添加数据 array = [1,2,3];rear=2;front=-1;
              队列满:true --> 2 -- 1 = 3
              队列空:false --> 2 == -1
            - 取出一个数据 array = [0,2,3];rear=2;front=0;
              队列满:false --> 2 - 0 = 3
              队列空:false --> 2 == 0
            - 取出所有数据 array = [0,0,0];rear=2;front=2;
              队列满:false --> 2 - 2 = 3
              队列空:true --> 2 == 2
            - 继续添加数据 array=[0,2,3] --> [1,2,3]
                         rear=0;front=0;
              队列满:false --> 0 - 0 = 3
              队列空:true --> 0 == 0 (条件错误)
        2. 修改定义
    */
    private int maxSize;
    private int rear;
    private int front;
    private int[] array;

    public TestCircularQueue(int size) {
    
    
        this.maxSize = size;
        array = new int[maxSize];
    }

    // 判断是否已满
    public boolean isFull() {
    
    
        return (rear + 1) % maxSize == front;
    }

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

    // 存储数据
    public void add(int value) {
    
    
        if (isFull()) {
    
    
            throw new RuntimeException("队列已满");
        }
        array[rear] = value;
        rear = (rear + 1) % maxSize;
    }

    // 取出数据
    public int get() {
    
    
        if (isEmpty()) {
    
    
            throw new RuntimeException("队列为空");
        }
        int value = array[front];
        array[front] = 0;
        front = (front + 1) % maxSize;
        return value;
    }

    // 打印所有数据
    public void printArray() {
    
    
        System.out.println(Arrays.toString(array));
    }
}
```# 三、队列

## 1. 介绍
  1. 队列是一个有序列表,可以通过数组或者链表实现
  2. 遵循先入先出的原则。
  3. 如下图:存入数据时,front不变,rear变化;取数据时,rear位置不变,front的位置变化

## 2. 图示

  图片站内找的![\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hwV4khKf-1649303240655)(https://secure2.wostatic.cn/static/nQwtdspuVpA6vWQBFmA1Aa/image.png)\]](https://img-blog.csdnimg.cn/3337adbcd1874b0cac88c51c594b9e8d.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6ZW_5rO96ZuF576O5L2g6ICB5amG,size_14,color_FFFFFF,t_70,g_se,x_16)
  - rear:队列的尾部
  - front:数据的头部

## 3. 数组实现队列

  - 代码

```java
package 二__队列;

/*
队列
场景:排队
介绍:先进先出



*/

import java.util.Queue;

public class Test {
    
    

    public static void main(String[] args) {
    
    
            test1();
    }

    // 数组队列模型
    public static void test1() {
    
    
        ArrayQueue arrayQueue = new ArrayQueue(10);
        arrayQueue.add(1);
        arrayQueue.add(2);
        arrayQueue.add(3);
        arrayQueue.add(4);
        arrayQueue.add(5);
        arrayQueue.add(6);
        arrayQueue.add(7);
        arrayQueue.add(8);
        arrayQueue.add(9);
        arrayQueue.add(10);
        arrayQueue.add(11);
        arrayQueue.showQueue();
        System.out.println("头部数据:"+arrayQueue.headQueue());
    }
}

// 数组队列
class ArrayQueue {
    
    
    private int maxSize;  // 最大容量
    private int front;  // 队列头
    private int rear;  // 队列尾
    private int[] arr; // 用来存储数据

    // 创建队列的构造器
    public ArrayQueue(int maxSize) {
    
    
        this.maxSize = maxSize;
        this.arr = new int[maxSize];
        this.front = -1;  // 指向队列头的前一个位置
        this.rear = -1;
    }

    public boolean isFull() {
    
    
        return rear == maxSize - 1;
    }

    public boolean isEmpty() {
    
    
        return front == rear;
    }

    // 添加
    public void add(int n) {
    
    
        // 判断是否满
        if (isFull()) {
    
    
            System.out.println("队列满,不可以添加数据");
            return;
        }
        // 尾部后移一位
        rear++;
        arr[rear] = n;
    }

    // 获取
    public int poll() {
    
    
        // 返回头部第一个
        if (isEmpty()) {
    
    
            System.out.println("队列为空");
            return -1;
        }
        front++;
        return arr[front];
    }

    //显示所有数据
    public void showQueue(){
    
    
        if(isEmpty()){
    
    
            System.out.println("队列为空");
            return;
        }
        for (int i : arr) {
    
    
            if(i != 0) System.out.println(i);
        }
    }

    // 显示队列头数据
    public int headQueue(){
    
    
        if(isEmpty()){
    
    
            System.out.println("队列为空");
            return -1;
        }
        return arr[front+1];
    }
}

  • Review code
/*
    队列基本要求:
    1. 先进先出
    2. rear 表示尾部
    3. front 表示头部
    4. array 表示存储数据的数组

    1. 每添加一个数据 rear+1;
    2. 每取出一个数据 front+1;
*/

// 数组队列
@Data
class TestArrayQueue{
    
    
    private int maxSize;
    private int rear ;
    private int front ;
    private int[] array;

    public TestArrayQueue(int  size){
    
    
        this.maxSize = size;
        array = new int[maxSize];
        rear = -1;
        front = -1;
    }

    // 判断是否已满
    public boolean isFull(){
    
    
        return rear-front == maxSize;

    }
    // 判断是否为空
    public boolean isEmpty(){
    
    
        return rear == front;
    }
    // 存储数据
    public void add(int value){
    
    
        if(isFull()){
    
    
            throw new RuntimeException("队列已满");
        }
        rear ++;
        array[rear] = value;
    }

    // 取出数据
    public int get(){
    
    
        if(isEmpty()){
    
    
            throw new RuntimeException("队列为空");
        }
        front ++;
        int value = array[front];
        array[front] = 0;
        return value;
    }

    // 打印所有数据
    public void printAll(){
    
    
        System.out.println(Arrays.toString(array));
    }
}
    // 测试 数组队列
    public static void testArrayQueue(){
    
    
        TestArrayQueue testArrayQueue = new TestArrayQueue(5);
        Scanner scanner = new Scanner(System.in);
        while (true){
    
    
            System.out.println("-------------------------------------");
            System.out.println("1) 添加数据");
            System.out.println("2) 获取数据");
            System.out.println("3) 打印所有数据");
            String s = scanner.nextLine();
            switch (s){
    
    
                case "1":{
    
    
                    System.out.print("输入数据:___");
                    int i = scanner.nextInt();
                    testArrayQueue.add(i);
                    System.out.println("输入成功");
                    System.out.println("---------------");
                    continue;
                }
                case "2":{
    
    
                    System.out.println(testArrayQueue.get());
                    continue;
                }
                case "3":{
    
    
                    testArrayQueue.printAll();
                    continue;
                }
            }
        }
    }

4. Arrays simulate ring queues

  1. question

    Arrays cannot be reused, one-time

    Use algorithm optimization to improve into a ring queue, use modulo algorithm to optimize

  2. analyze

    • front now points to the first element of the queue (was pointing to the previous element)

    • rear meaning adjustment: rear points to the position after the last element of the queue. Make a space to make a promise.

      It is convenient to judge whether front and rear are equal: the initial value of rear is 0.

    • When the queue is full, the condition is (rear+1)%maxSize = front【full】

    • When the queue is empty, rear == front(0) [empty]

    [External link picture transfer failed, the source site may have an anti-theft link mechanism, it is recommended to save the picture and upload it directly (img-I7SmWrMv-1649303240655)(https://secure2.wostatic.cn/static/fJFKyJNbjkHu2XfzmjGJHf/image.png)]

  3. the code

the code

package 二__队列;
/*
    Date:2022/4/6
    author: Blue Friday
    describe: //todo
*/


public class Test2 {
    
    
    public static void main(String[] args) {
    
    
        CircleArrayQueue circleArrayQueue = new CircleArrayQueue(4);
        circleArrayQueue.add(1);
        circleArrayQueue.add(2);
        circleArrayQueue.add(3);
        circleArrayQueue.add(4);
        System.out.println(circleArrayQueue.poll());
        System.out.println(circleArrayQueue.poll());
        System.out.println(circleArrayQueue.poll());
        System.out.println(circleArrayQueue.poll());
//        System.out.println(circleArrayQueue.poll());
        circleArrayQueue.add(60);
        System.out.println(circleArrayQueue.poll());

    }
}

// 环形队列
class CircleArrayQueue {
    
    
    private int maxSize;  // 最大容量
    private int front;  // 队列头
    private int rear;  // 队列尾
    private int[] arr; // 用来存储数据

    // 创建队列的构造器
    public CircleArrayQueue(int arrmaxSize) {
    
    
        maxSize = arrmaxSize +1;
        this.arr = new int[maxSize];
        this.front = 0;  // 指向队列头的前一个位置
        this.rear =  0;  // 指向队列尾
    }

    // 满队列条件
    public boolean isFull() {
    
    
        return (rear + 1 )%maxSize == front;
    }

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

    // 添加
    public void add(int n) {
    
    
        // 判断是否满
        if (isFull()) {
    
    
            System.out.println("队列满");
            return;
        }
        arr[rear] = n;
        // 将rear后移,这里需要取模,
        rear = (rear + 1)%maxSize;
    }

    // 获取
    public int poll() {
    
    
       if(isEmpty()){
    
    
           throw new RuntimeException("队列空");
       }
       int value = arr[front];
       front = (front +1) % maxSize;
       return value;
    }

    //显示所有数据
    public void showQueue() {
    
    
        if (isEmpty()) {
    
    
            System.out.println("队列为空");
            return;
        }
        // 遍历多少元素
        // 有效数据个数
        int size = size();
        for (int i = 0; i < front + size ; i++) {
    
    
            System.out.println(i % maxSize+": "+arr[i % maxSize]);

        }
    }

    // 显示队列头数据
    public int headQueue() {
    
    
        if (isEmpty()) {
    
    
            System.out.println("队列为空");
            return -1;
        }
        return arr[front];
    }
    // 队列有效个数
    public int size(){
    
    
        return (rear + maxSize - front)%maxSize;
    }
}

Review code

  // 测试环形数组
    public static void testCircularQueueC() {
    
    
        TestCircularQueue testCircularQueue = new TestCircularQueue(5);
        Scanner scanner = new Scanner(System.in);
        while (true) {
    
    
             try {
    
    
                 System.out.println("-------------------------------------");
                 System.out.println("1) 添加数据");
                 System.out.println("2) 获取数据");
                 System.out.println("3) 打印所有数据");
                 String s = scanner.nextLine();
                 switch (s) {
    
    
                     case "1": {
    
    
                         System.out.print("输入数据:___");
                         int i = scanner.nextInt();
                         testCircularQueue.add(i);
                         System.out.println("输入成功");
                         System.out.println("---------------");
                         continue;
                     }
                     case "2": {
    
    
                         System.out.println(testCircularQueue.get());
                         continue;
                     }
                     case "3": {
    
    
                         testCircularQueue.printArray();
                         continue;
                     }
                 }
             }catch (Exception e){
    
    
                 System.out.println(e.getMessage());
             }
        }
    }
// 环形数组队列
@Data
class TestCircularQueue {
    
    
    /*
        1. 修改定义 rear 初始  = 0; front = 0;
        2. 队列满:( rear + 1 )%maxSize = front;
        3. 队列空:rear == front
        举例:
        1. 不修改定义
            - 初始化数组(指向前一个元素): rear = -1 ;front = -1;maxSize = 3;
              队列满:rear - front == maxSize;
              队列空:rear == front
            - 添加数据 array = [1,2,3];rear=2;front=-1;
              队列满:true --> 2 -- 1 = 3
              队列空:false --> 2 == -1
            - 取出一个数据 array = [0,2,3];rear=2;front=0;
              队列满:false --> 2 - 0 = 3
              队列空:false --> 2 == 0
            - 取出所有数据 array = [0,0,0];rear=2;front=2;
              队列满:false --> 2 - 2 = 3
              队列空:true --> 2 == 2
            - 继续添加数据 array=[0,2,3] --> [1,2,3]
                         rear=0;front=0;
              队列满:false --> 0 - 0 = 3
              队列空:true --> 0 == 0 (条件错误)
        2. 修改定义
    */
    private int maxSize;
    private int rear;
    private int front;
    private int[] array;

    public TestCircularQueue(int size) {
    
    
        this.maxSize = size;
        array = new int[maxSize];
    }

    // 判断是否已满
    public boolean isFull() {
    
    
        return (rear + 1) % maxSize == front;
    }

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

    // 存储数据
    public void add(int value) {
    
    
        if (isFull()) {
    
    
            throw new RuntimeException("队列已满");
        }
        array[rear] = value;
        rear = (rear + 1) % maxSize;
    }

    // 取出数据
    public int get() {
    
    
        if (isEmpty()) {
    
    
            throw new RuntimeException("队列为空");
        }
        int value = array[front];
        array[front] = 0;
        front = (front + 1) % maxSize;
        return value;
    }

    // 打印所有数据
    public void printArray() {
    
    
        System.out.println(Arrays.toString(array));
    }
}

Guess you like

Origin blog.csdn.net/m0_56186460/article/details/124225099