数组模拟环形队列实现

环形队列介绍

环形队列是一种头尾相连的结构,可以用数据或者链表来实现,本文通过数组实现。

1.队列的基本特性是先进先出,所以添加元素时尾部指针往后移,获取元素时,从队列头获取。
2.队列为空时,头尾指针都为0
添加元素时指针变化
add(1) tail 0 -> 1 head 0
add(2) tail 1 -> 2 head 0
add(3) tail 2->3 head 0
···
add(7) tail 6 ->7 head 0 此时队列满

获取元素时指针变化(接上面的数据)
get 获取元素1 head 0 -> 1
get 获取元素2 head 1 -> 2
···
get 获取元素 7 head=tail-7 此时队列为空(因为预留了一个空位给尾部指针)

在这里插入图片描述
一.通过数组实现环形队列

package com.structure.queue;


import java.util.Scanner;

/**
 * @author zzq
 * @Date 2021-07-14 17:18
 */
public class CircleQueueDemo {

    public static void main(String[] args) {
        System.out.println("测试环形队列----");
        CircleQueue circleQueue = new CircleQueue(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':
                    circleQueue.showQueue();
                    break;
                case 'a':
                    System.out.println("输出一个数");
                    int nextInt = scanner.nextInt();
                    circleQueue.add(nextInt);
                    break;
                case 'g':
                    try {
                        int i = circleQueue.get();
                        System.out.println("得到的数据:"+i);
                    }catch (Exception e){
                        System.out.println(e.getMessage());
                    }

                    break;
                case 'h':
                    try {
                        int i = circleQueue.getHead();
                        System.out.println("队列头部数据:"+i);
                    }catch (Exception e){
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'e':
                    scanner.close();
                    loop = false;
                    break;
                default:
                    break;
            }
        }
        System.out.println("程序退出");
    }

}

class CircleQueue{

    /**
     * 存放元素的数组
     */
    private int[] arr;

    /**
     * 数组大小,即最大元素个数
     */
    private int maxSize;

    /**
     * 头部指针,指向队列的第一个元素
     */
    private int head;

    /**
     * 尾部指针,指向最后一个元素的后一个位置
     * 这里做一个约定,就是我们队列最后会留一个位置出来,用于记录这个tail的指针
     * lg:
     *  1.队列长度为8,实际最多能存储7个元素,因为要留一个位置给tail的指针
     *  2.初始时,head=tail=0
     */
    private int tail;

    /**
     * 初始化一个队列
     * @param maxSize
     */
    public CircleQueue(int maxSize) {
        this.maxSize = maxSize;
        this.arr = new int[maxSize];
        //这里head=tail=0  不写了,因为int类型的默认值就是0
    }

    /**
     * 判断队列是否为空,当头部和尾部指针重合时,队列为空
     * @return
     */
   public boolean isEmpty(){

       return head == tail;
   }

    /**
     * 队列是否满
     * 因为是一个环形队列,所以正常情况下tail 在 head 的前一个位置的时候说明队列满了
     * 因为是环形队列,所以要跟maxSize取模
     * (tail + 1) % maxSize == head
     * @return
     */
    public boolean isFull(){

        return (tail + 1) % maxSize == head;
    }

    /**
     * 添加元素,尾部指针移动
     * @param ele
     */
    public void add(int ele){
        if(isFull()){
            System.out.println("队列已满,加不进去");
            return;
        }

        //此处不能直接tail++,因为是环形队列,直接++可能会导致下标越界
        //想象一下,此时head=6,tail=7 加一个元素tail++=8 会越界,那么要重新从0开始算下标
        arr[tail] = ele;
        tail = (tail+1) % maxSize;
    }

    /**
     * 先进先出,从头部取数据
     * @return
     */
    public int get(){
        if(isEmpty()){
            throw new RuntimeException("队列是空的");
        }
        int value = arr[head];
        head = (head+1) % maxSize;
        return value;
    }

    /**
     * 获取队列中实际的元素个数,因为留了一个空位,比如队列长度为8,填满时实际元素只有7个
     * @return
     */
    public int getSize(){
        //这里加上tail-head+maxSize 加maxSize是因为有时候 tail不一定比head大
        // 出现特殊情况比如多去存取之后, tail=1 head=2
        return (tail-head+maxSize) % maxSize;
    }

    public void showQueue(){
        if(isEmpty()){
            System.out.println("队列为空,没有数据");
            return;
        }

        for (int i = head; i < head+getSize(); i++) {
            System.out.printf("arr[%d]=%d\n",i % maxSize,arr[i % maxSize]);
        }
    }

    public int getHead(){
        if(isEmpty()){
            throw new RuntimeException("队列是空的");
        }
        return arr[head];
    }
}

运行示例
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值