数据结构——队列(Java实现)

1.2 队列

  • 队列特性: 先进先出
  • 队列是个有序列表,可以使用数组链表实现

1.2.1 数组模拟队列(无环形)

  • 队列本身就是有序列表,如果使用数组的结构来实现队列,那么队列数组的声明如下图:
    在这里插入图片描述

  • 因为队列的输出、输入是分别从前后端来处理,因此需要两个变量 front 及 rear 分别记录队列前后端的下标, front 会随着数据输出而改变,而 rear 则是随着数据输入而改变,如队列介绍中图所示

  • maxSize是队列的最大容量

  • 入队addQueue()思路分析:

    • 1.入队时,将rear的指针+1,并且注意当队列为的时候font == rear
    • 2.若指针rear小于队列的最大下标maxSize-1时,才能够存入数据,否则的话无法存入数据 。注意当队列为的时候 rear == maxSize -1
  • 注意:font并没有直接指向队列数据的第一位,而是指向队列头的前一位,所以需要读取队列头的时候需要使用font+1

  • 注意:本队列的缺点,没有实现环形队列,出队的数据其实还是在队列数组内,只是指向队列头的指针变化了

实现代码

import java.util.List;
import java.util.Scanner;

class MyQueue{
    private int maxSize;// 队列最大容量
    private int font;// 队列头指针
    private int rear;// 队列尾指针
    private int[] arrayQueue;// 队列数组
    public MyQueue(int maxSize){ // 初始化队列
        this.maxSize = maxSize;
        font = -1;
        rear = -1;
        arrayQueue = new int[maxSize];
    }
    public boolean isEmpty(){ // 判断队列是否为空
        return font == rear;
    }
    public boolean isFull(){ // 判断队列是否满了
        return rear == maxSize-1;
    }
    public void addQueue(int a){
        if(!isFull()){
            rear++;
            arrayQueue[rear] = a;
        }else
            System.out.println("队列满了!");
    }
    public int popQueue() {
        if (!isEmpty()) {
            font++;
            return arrayQueue[font];
        } else {
            System.out.println("队列为空!");
            return -1;
        }
    }
    public int getHead(){
        if (!isEmpty()){
            return arrayQueue[font+1];
        }else {
            throw new RuntimeException("队列为空");
        }
    }
    public void showQueue(){
        if (!isEmpty()){
            int count = 0;
            for(int i=font+1;i<rear+1;i++){
                System.out.println("Queue["+count+"]: "+arrayQueue[i]);
                count++;
            }
        }else
            System.out.println("队列为空!");
    }
}
public class ArrayQueueDemo01 {
    public static void main(String[] args) {
        System.out.print("请输入队列的最大容量:");
        Scanner scanner = new Scanner(System.in);
        int maxSize = scanner.nextInt();
        MyQueue myQueue = new MyQueue(maxSize);
        boolean isOk = true;
        while (isOk){
            System.out.println("s(show):显示全部队列");
            System.out.println("a(add):入队");
            System.out.println("p(pop):出队");
            System.out.println("h(getHead):获取队列头");
            System.out.println("e(exit):退出");
            System.out.print("请输入命令: ");
            char key = scanner.next().charAt(0);
            switch (key){
                case 's': {
                    myQueue.showQueue();
                    break;
                }
                case 'a': {
                    System.out.print("请输入添加数据: ");
                    int add = scanner.nextInt();
                    myQueue.addQueue(add);
                    System.out.println("入队: "+add);
                    break;
                }
                case 'p': {
                    System.out.println("出队: "+myQueue.popQueue());
                    break;
                }
                case 'h': {
                    System.out.println("队列头: "+myQueue.getHead());
                    break;
                }
                case 'e': {
                    System.out.println("退出");
                    isOk = false;
                    break;
                }
                default:
                    System.out.println("输入错误!");
            }
        }
    }
}

1.2.2 环形数组模拟队列

优化

  • font指针的初始值为0,font直接指向队列的第一个数据,判断队列为的条件为rear == font

  • rear指向队列的最后一个数据的后面一个位置,所以rear指针的初始值为0(前一位是-1),即

    arrayQueue[rear-1] = 最后一个数据

  • 队列的条件是:(rear +1) % maxSize = font

  • 为了区分队满和队空,所以需要浪费一个空间作为指针的停靠,因此才造成了队满条件为**(rear+1)% maxSize = font**,

    • 为什么需要+1:因为这个时候实际上rear指针在font指针前一个位置(浪费的空间内)
    • 为什么需要%maxSize:避免出现数组下标越界的问题
  • 所以整个队列内有效数据的个数为:((rear-1)-font+1)% maxSize,即**(rear-font+maxSize)% maxSize**

    • 为什么需要添加maxSize?

    • 因为队列是个循环队列,那么rear和font的下标值是一直处于变化的,所以会出现rear小于font的情况,这个时候只需要加上一个maxSize就可以将rear-font的值从负转为正,可以看下图帮助理解:
      在这里插入图片描述

  • 入队时rear : rear = (rear+1) % maxSize

  • 出队时font : font = (font+1) % maxSize

  • 如图:

    • maxSize = 8,rear = 8, font = 1
    • (rear+1) % maxSize = 1 = font 队满
      在这里插入图片描述
      一篇讲的很好的博客 通俗易懂讲解循环队列原理_派大星⭐的博客-CSDN博客(https://blog.csdn.net/qq_44280408/article/details/104017937)

实现代码

import java.util.Scanner;

class circleQueue{
    private int maxSize;// 队列最大容量
    private int font;// 队列头指针
    private int rear;// 队列尾指针
    private int[] arrayQueue;// 队列数组
    public circleQueue(int maxSize){ // 初始化队列
        this.maxSize = maxSize+1;
        font = 0;
        rear = 0;
        arrayQueue = new int[this.maxSize];
    }
    public boolean isEmpty(){ // 判断队列是否为空
        return font == rear;
    }
    public boolean isFull(){ // 判断队列是否满了
        return (rear+1)%maxSize == font;
    }
    public void addQueue(int a){ // 入队
        if(!isFull()){
            arrayQueue[rear%maxSize] = a;
            rear = (rear+1) % maxSize;
        }else
            System.out.println("队列满了!");
    }
    public int popQueue() { // 出队
        if (!isEmpty()) {
            int temp = arrayQueue[font];
            font = (font+1) % maxSize;
            return temp;
        } else {
            System.out.println("队列为空!");
            return -1;
        }
    }
    public int getHead(){
        if (!isEmpty()){
            return arrayQueue[font];
        }else {
            throw new RuntimeException("队列为空");
        }
    }
    public void showQueue(){
        if (!isEmpty()){
            int count = 0;
            for(int i=font;i<font+getNums();i++){
                // 注意要防止下标越界
                System.out.println("Queue["+count+"]: "+arrayQueue[i%maxSize]);
                count++;
            }
        }else
            System.out.println("队列为空!");
    }
    public int getNums(){ // 获取当前队列内有效数据的个数
        return (rear - font + maxSize) % maxSize;
    }
}
public class ArrayQueryDemo02 {
    public static void main(String[] args) {
        System.out.print("请输入队列的最大容量:");
        Scanner scanner = new Scanner(System.in);
        int maxSize = scanner.nextInt();
        circleQueue circleQueue = new circleQueue(maxSize);
        boolean isOk = true;
        while (isOk){
            System.out.println("s(show):显示全部队列");
            System.out.println("a(add):入队");
            System.out.println("p(pop):出队");
            System.out.println("h(getHead):获取队列头");
            System.out.println("e(exit):退出");
            System.out.print("请输入命令: ");
            char key = scanner.next().charAt(0);
            switch (key){
                case 's': {
                    circleQueue.showQueue();
                    break;
                }
                case 'a': {
                    System.out.print("请输入添加数据: ");
                    int add = scanner.nextInt();
                    circleQueue.addQueue(add);
                    System.out.println("入队: "+add);
                    break;
                }
                case 'p': {
                    System.out.println("出队: "+circleQueue.popQueue());
                    break;
                }
                case 'h': {
                    System.out.println("队列头: "+circleQueue.getHead());
                    break;
                }
                case 'e': {
                    System.out.println("退出");
                    isOk = false;
                    break;
                }
                default:
                    System.out.println("输入错误!");
            }
        }
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值