【数据结构+算法】队列——用数组实现环形队列(JAVA)

在我上一个博客中,我们提到数组实现队列时,不能实现代码的复用,优化方法是可以改成一个环形的数组(进行取余)。所以本次我将总结如何用数组实现环形队列。

思路:

1、对front变量进行一个调整:front指向队列的第一个元素,即arr[front]为队列的第一个元素;front=0

2、对rear变量也进行相应的调整:reart指向队列最后一个元素的后一个位置,预留一个空间;rear=0

3、队满:(rear+1) % maxSize = front

4、对空:rear == front

5、队列中的有效数据:(rear + maxSize - front) % maxSize
(rear可能小于maxSize,取余是为了获取在环形队列上真实位置)

具体实现代码如下:
(1)、判断队列是否满
(2)、判断队列是否为空
(3)、添加数据到队列中
(4)、获取队列的数据,出队列;
(5)、显示当前队列数据;
(6)、显示队列的头数据,注意不是取出数据;

package com.ycx.queue;

import java.util.Scanner;

public class CircleArrayQueueDemo {
    public static void main(String[] args) {

        //测试
        System.out.println("测试数组模拟环形队列");

        //创建一个环形队列
        CircleArray queue = new CircleArray(4);//有一个空位置 有效数据最大是3
        char key = ' ';//接受用户输入
        Scanner input = new Scanner(System.in);
        boolean flag = true; //控制循环 默认死循环

        //输出菜单
        while (flag){
            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=input.next().charAt(0);//接受收一个字符
            switch (key){
                case 's':
                    queue.showQueue();
                    break;
                case 'a':
                    System.out.println("输一个数");
                    int val=input.nextInt();
                    queue.addQueue(val);
                    break;
                case 'g':   //取出数据  因为方法里面抛出了异常 所以这里需要捕获
                    try{
                        int res=queue.getQueue();
                        System.out.printf("取出的数据为%d\n",res);
                    }catch (Exception e){
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'h':
                    try{
                        int res=queue.headQueue();
                        System.out.printf("队列头的数据为%d\n",res);
                    }catch (Exception e){
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'e':    //退出程序
                    input.close();//关闭
                    flag=false;
                    break;

                default:
                    break;
            }
        }
        System.out.println("程序退出");
    }
}


class CircleArray{
    private  int maxSize;
    //表示数组的最大容量
    private  int front;
    //front变量含义做一个调整:指向队列的第一个元素,arr[front]即为队列的第一个元素
    //front=0
    private  int rear;
    //rear变量含义做一个调整:rear指向队列的最后一个元素的后一个位置,预留一个位置
    //rear=0
    private  int[] arr;
    // 该数组用于存放数据,模拟队列


    public CircleArray(int arrMaxSize){
        maxSize = arrMaxSize;
        arr = new int[maxSize];
        front=0;
        rear=0;
    }


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

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


    //3.添加数据到队列中
    public void addQueue(int n) {
        //判断队列是否为满
        if (isFull()) {
            System.out.println("队列已满,不能加入数据");
        }
        arr[rear] = n;
        //直接将数据加入 因为rear本身指的就是 后一个元素
        rear = (rear + 1) % n;
        //将rear 后移 并取模 (环形 当rear走到最后一个位置时,取模就可以到前面的位置)
    }

        //4.获取队列的数据,出队列
        public  int getQueue(){
            if(isEmpty()){
                throw new RuntimeException("队列空,不能取数据");
            }

            //这里需要分析出front是指向队列的第一个元素
            //①. 先把front对应的值保留到一个临时变量;
            //②. 将front后移,考取取模(因为front也可能走到最后一个元素,就会越界)
            //③. 将临时保存的变量返回
            int value = arr[front];
            front = (front+1) % maxSize;
            return value;
        }


        //5.显示当前队列数据
    public void showQueue() {
        //遍历
        if(isEmpty()){
            System.out.println("当前队列为空");
            return;
        }

        //思路: 从front开始遍历 一共有front+有效数据个数
        for (int i = front ;i <front+size(); i++) {
            System.out.printf("arr[%d]=%d\n",i%maxSize,arr[i%maxSize]); //格式化输出
                                             // i可能也会超出下标(环形)
        }
    }

    //求出当前有效数据个数
    public int size(){
        return (rear+maxSize-front)%maxSize;
        // rear=1 front=0 maxSize=3
    }


    //6.显示队列的头数据,注意不是取出数据
    public int headQueue(){
        if(isEmpty()){
            throw new RuntimeException("队列为空");
        }
        return arr[front]; //注意:front本身就指向第一个元素
    }



}

运行结果如下:
在这里插入图片描述

发布了27 篇原创文章 · 获赞 32 · 访问量 2837

猜你喜欢

转载自blog.csdn.net/m0_45097186/article/details/104226769