[java]-算法与数据结构-第三章-队列

三、队列

1. 介绍

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

2. 图示

图片站内找的[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hwV4khKf-1649303240655)(https://secure2.wostatic.cn/static/nQwtdspuVpA6vWQBFmA1Aa/image.png)]

  • rear:队列的尾部
  • front:数据的头部

3. 数组实现队列

代码

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

复盘代码

/*
    队列基本要求:
    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. 数组模拟环形队列

  1. 问题

    数组不能复用,一次性

    使用算法优化改进成环形队列,使用取模算法优化

  2. 分析

    • front 现在指向队列第一个元素(原来指向前一个元素)

    • rear含义调整:rear指向队列的最后一个元素的后一个位置。空出一个空间做一个约定。

      方便判断 front 和 rear是否相等:rear初始值为0。

    • 当队列满时,条件是(rear+1)%maxSize = front【满】

    • 当队列为空时,rear == front (0)【空】

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I7SmWrMv-1649303240655)(https://secure2.wostatic.cn/static/fJFKyJNbjkHu2XfzmjGJHf/image.png)]

  3. 代码

代码

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

复盘代码

  // 测试环形数组
    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];
    }
}

  • 复盘代码
/*
    队列基本要求:
    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. 数组模拟环形队列

  1. 问题

    数组不能复用,一次性

    使用算法优化改进成环形队列,使用取模算法优化

  2. 分析

    • front 现在指向队列第一个元素(原来指向前一个元素)

    • rear含义调整:rear指向队列的最后一个元素的后一个位置。空出一个空间做一个约定。

      方便判断 front 和 rear是否相等:rear初始值为0。

    • 当队列满时,条件是(rear+1)%maxSize = front【满】

    • 当队列为空时,rear == front (0)【空】

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I7SmWrMv-1649303240655)(https://secure2.wostatic.cn/static/fJFKyJNbjkHu2XfzmjGJHf/image.png)]

  3. 代码

代码

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

复盘代码

  // 测试环形数组
    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));
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

长泽雅美你老婆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值