基础数据结构—队列,Java模拟队列,循环队列

先进先出的队列

动图

队列的相关操作

push x 将x加入队尾,保证x为int型整数

pop 输出队首,并让队首出队

front 输出队首值,不出队

input

6
push 1
pop
front
push 2
push 3
pop

output

1
error
2
1)Java模拟队列

①通过数组

图示思路:

代码实现:

class myQueue{
    int[] data; //用数组来模拟队列中存放的数据
    int size=0; //队列中元素的个数
    int maxSize;    //队列中最多存放数据的个数
    myQueue(){}
    myQueue(int maxSize){ 
        this.maxSize=maxSize;
        data = new int[maxSize];    //一定记得初始化数组,不然后续操作空指针
    }
    //入队
    void push(int val){
        if(this.size==this.maxSize){
            System.out.println("error");
        }else{
            data[this.maxSize-size-1]=val;
            this.size++;
        }
    }
    //出队
    void pop(){
        if(this.size==0){ System.out.println("error"); }
        else{
            System.out.println(data[this.maxSize-1]);
            if(size>=2){
                this.size--;
                for(int i=0;i<size;i++){
                    data[this.maxSize-i-1]=data[this.maxSize-i-2];
                }
            }else{
                this.size--;
            }
        }
    }
    //查看队首元素
    void front(){
        if(this.size==0){ System.out.println("error"); }
        else{ System.out.println(data[maxSize-1]); }
    }
}

②通过集合

图示思路:

代码实现:

public class Main{
    static ArrayList list = new ArrayList<>();
    static void push(int x){
        list.add(x);
    }
    //注意Object返回值类型
    static Object pop(){
        if(!list.isEmpty()){
            int str = (Integer)list.get(0); //ArrayList第一元素就是最先进去的
            list.remove(0);
            return str;
        }else{ return "error"; }
    }
    static Object front(){
        if(!list.isEmpty()){
            return list.get(0);
        }else{
            return "error";
        }
    }
    public static void main(String[] args) {
        ...
    }
}
2)循环队列

操作

push x:将x加入到循环队列尾端。若循环队列已满,输出"full"(不含引号),否则不输出任何内容。保证x为int型整数。
front:输出队首元素,队首不出队。若队列为空,输出"empty"(不含引号)。
pop:输出队首元素,且队首出队。若队列为空,输出"empty"(不含引号)。

循环队列组成

存放元素的数组,队头指针, 队尾指针。

队头指针:front,指向队头元素;队尾指针:rear,指向队尾的下一个元素

arr[front]的值就是当前队列的队头元素值

arr[rear-1]的值就是当前队列的队尾元素值

  • 初始状态:front=rear=0,队列为空
  • 某一状态:front=0,rear=3
    • 例如数组arr[5]实时情况为:{1,2,3,0,0},队头元素arr[0]=1,队尾元素arr[2]=3

解释:每次push一个元素到队列尾部,rear++,当arr[4]放入元素,rear将会达到5

  • 队列装满状态:front=0=rear??

但是数组下标为0-4,5并没有意义。所以rear如果等于5了应该再将它置为0。

改进:元素入队时rear=(rear+1)%maxSize,假如maxSize=5,rear+1=5时对maxSize取余为0达到效果。

发现问题:无法通过判断front==rear来确定循环队列是否装满。

牺牲一个存储单元,(rear+1)%maxSize=front的话,证明队满。rear=front的话,证明队空。

  • 有元素出队的情况:front=1,rear=3
    • 例如数组arr[5]实时情况为:{0,2,3,0,0},队头元素arr[0]出队了,队尾元素arr[2]=3

解释:每一次pop队头元素,front++,上述情况如果2,3再依次出队,front=rear=3,队空了。

改进:元素出队front=(front+1)%maxSize

循环队列长度计算公式:(rear-front+maxSize)%maxSize

{0,2,3,0,0}:front=1,rear=3,size=(3-1+5)%5=2

{6,0,3,4,5}:front=2,rear=1,size=(1-2+5)%5=4

代码实现:

/**
 * 循环队列,队列元素存到数组中
 */
import java.util.Scanner;

public class queue3 {
    int[] data;
    int maxSize;

    static int front=0;
    static int rear=0;

    queue3(){}

    queue3(int n){
        maxSize=n+1;
        data = new int[maxSize];
    }

    String push(int x){
        if((rear+1)%maxSize==front){
            return "full";
        }else{
            data[rear]=x;
            rear=(rear+1)%maxSize;
            return "";
        }
    }
    //注意Object返回值类型
    Object pop(){
        if(!(rear==front)){
            int str = data[front];
            front=(front+1)%maxSize;
            return str;
        }else{ return "empty"; }
    }
    //返回队头元素
    Object front(){
        if(!(rear==front)){
            return data[front];
        }else{
            return "empty";
        }
    }

    int queueLength(){
        return (rear-front+maxSize)%maxSize;
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入循环队列大小和操作次数(空格分开)");
        String str = sc.nextLine();
        String[] strArr = str.split(" ");
        queue3 q = new queue3(Integer.parseInt(strArr[0]));
        int i = Integer.parseInt(strArr[1]);
        for(;i>0;i--){
            String str2 = sc.nextLine();
            String[] strArr2 = str2.split(" ");
            switch(strArr2[0]){
                case "push":
                str2=q.push(Integer.parseInt(strArr2[1]));
                if(str2.equals("full")){
                    System.out.println(str2);
                }
                break;
                case "pop":
                System.out.println(q.pop());
                break;
                case "front":
                System.out.println(q.front());
                break;
            }
        }
    }
   
}
posted @   BAISHUN66  阅读(82)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示