两种队列

该博客探讨了如何使用数组模拟顺序队列,以及如何通过优化将其转化为环形队列以提高效率。顺序队列遵循先入先出原则,但一旦满就不能再添加数据。环形队列则解决了这一问题,通过数组的取模运算实现队列的循环使用,使得在满时仍能继续添加数据。博客详细展示了两种队列的代码实现,并提供了用户交互的示例。
摘要由CSDN通过智能技术生成

队列是一个有序链表,可以用数组或是链表来实现

遵循先入先出原则。即:先存入队列的数据,要先取出。后存入的要后取出

数组模拟队列

1.顺序队列

示意图:(使用数组模拟队列示意图)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2Mu1B8OD-1613481581393)(C:\Users\50730\AppData\Roaming\Typora\typora-user-images\image-20210216113646118.png)]

  • front是头部,rear尾部。存入数据时候尾部移动,头部不动。取出数据时候尾部不动,头部移动。
  • front随着数据输出而变化,rear随着数据输入而变化。
  • front指向队列头部,front指向的是队列头数据的前一个位置(即不是队列的第一个数据)。rear指向队列尾,指向队列尾的数据(即就是队列最后一个数据)

代码实现:



package com.icon.QueueTest;

import jdk.internal.org.objectweb.asm.tree.IntInsnNode;

import java.util.Queue;
import java.util.Scanner;

/**
 * ClassName: ArrayQueueDemo
 * Description:数组模拟顺序队列
 * date: 2021/2/16 11:49
 *
 * @author:icon
 * @version:
 * @since JDK 1.8
 */
public class ArrayQueueDemo {
    public static void main(String[] args) {
        ArrayQueue queue = new ArrayQueue(3);
        char key ; //接收用户输入
        Scanner scanner = new Scanner(System.in);//
        boolean loop = true;
        while (loop) {
            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): 查看队列头的数据");
            key = scanner.next().charAt(0);//接收一个字符
            switch (key) {
                case 's':
                    try {
                        queue.getAllDate();
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'a':
                    System.out.println("请输入您想要添加的数据");
                    int n = scanner.nextInt();
                    try {
                        queue.addDate(n);
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'g':
                    try {
                        int res = queue.getFront();
                        System.out.printf("取出的数据是%d\n", res);
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'h':
                    try {
                        queue.headQueue();
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'e':
                    scanner.close();
                    loop = false;
                    break;
            }
        }
        System.out.println("程序退出~~");
    }
}

class ArrayQueue {
    private int maxSize;//队列最大容纳的值
    private int front;//指向队列的头部
    private int rear;//指向队列的尾部的后一个元素
    private int[] queue;//数组模拟队列

    public ArrayQueue(int maxSize) {
        this.maxSize = maxSize;
        this.front = 0;
        this.rear = 0;
        this.queue = new int[maxSize];
    }

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

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

    //向队列中添加数据
    public void addDate(int n) {
        if (isFull()) {
            throw new RuntimeException("队列已满,无法添加");
        }else{
            rear++;
            queue[rear] = n;
        }


    }

    // 获取队列的数据, 出队列
    public int getFront() {
        if (isEmpty()) {
            throw new RuntimeException("当前队列为空");
        } else {
            front++;
            return queue[front];
        }
    }

    //获取队列所有数据
    public int getAllDate() {

        if (isEmpty()) {
            throw new RuntimeException("此时队列为空");
        } else {
            for (int i = 0; i < queue.length; i++) {
                System.out.printf("arr[%d]=%d\n", i, queue[i]);
            }
        }
        return 0;
    }

    //获取队列的头数据
    public int headQueue() {
        if (isEmpty()) {
            throw new RuntimeException("数组为空");
        } else {
            return queue[front + 1];
        }
    }
}

问题分析并优化:

1)目前数组使用一次就不能用,没有达到复用的效果

2)将这个数组使用算法,改进成一个环形的数组(利用取模%)

2.环形队列

思路如下:

  • front变量的含义进行调整:front就指向队列的第一个元素,也就是说arr[front] 就是队列的第一个元素
  • rear变量的含义进行调整:rear指向队列的最后一个元素的后一个位置,因为希望空出一个空间作为约定,rear的初始值=0
  • 当队列满时,条件是(rear+1)%maxSize==front【满】
  • 当队列为空时,条件是 rear == front【空】
  • 此时,队列中的有效数据个数为 (rear+maxSize-front)%maxSize
  • 这是,我们在原来队列的基础上,得到一个环形队列

示意图:
在这里插入图片描述


代码实现:

package com.icon.QueueTest;

import java.util.Scanner;

/**
 * ClassName: CircleArrayQueueDemo
 * Description:数组模拟循环队列(空出一位法)
 * date: 2021/2/16 14:51
 *
 * @author:icon
 * @version:
 * @since JDK 1.8
 */
public class CircleArrayQueueDemo {
    public static void main(String[] args) {
        CircleArrayQueue queue = new CircleArrayQueue(4);
        char key; //接收用户输入
        Scanner scanner = new Scanner(System.in);//
        boolean loop = true;
        while (loop) {
            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): 查看队列头的数据");
            key = scanner.next().charAt(0);//接收一个字符
            switch (key) {
                case 's':
                    try {
                        queue.getAllDate();
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'a':
                    System.out.println("输出一个数");
                    int value = scanner.nextInt();
                    queue.addDate(value);
                    break;
                case 'g':
                    try {
                        int res = queue.getDate();
                        System.out.printf("取出的数据是%d\n", res);
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'h':
                    try {
                        queue.HeadDate();
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'e':
                    scanner.close();
                    loop = false;
                    break;
            }
        }
        System.out.println("程序退出~~");
    }
}

class CircleArrayQueue {
    private int maxSize;//队列最大容纳的值
    private int front;//指向队列的头部
    private int rear;//指向队列的尾部的后一个元素
    private int[] queue;//数组模拟队列

    public CircleArrayQueue(int maxSize) {
        this.maxSize = maxSize;
        queue=new int[maxSize];
    }

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

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

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

    }

    // 获取队列的数据, 出队列
    public int getDate() {
        if (isEmpty()) {
            throw new RuntimeException("此时队列没有数值");
        } else {
            int value = queue[front];
            front = (front + 1) % maxSize;
            return value;
        }
    }


    //显示队列的所有元素
    public void getAllDate() {
        if (isEmpty()) {
            throw new RuntimeException("当前队列为空值");
        } else {
            for (int i = front; i < front+getSize(); i++) {
                System.out.printf("arr[%d]=%d\n", i % maxSize, queue[i % maxSize]);
            }
        }
    }

    //获取当前对类的有效元素个数
    public int getSize() {
        return (rear + maxSize - front) % maxSize;
    }


    // 显示队列的头数据, 注意不是取出数据
    public int HeadDate() {
        if (isEmpty()) {
            throw new RuntimeException("队列空的,没有数据~~");
        } else
            return queue[front];
    }
}

未完…

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值