数据结构——循环队列(GIF图解)

循环队列

数组队列的出队操作的复杂度是O(n),性能很差,解决方法就是使用循环队列(Loop Queue)
在循环队列中,需要对队为空和队为满的时候进行判断,为了区分队空和队满两个条件,需要浪费capacity一个空间,让rear指针一直指向一个空的位置;

当 rear= =front 时,队为空;
当 (rear+1)%n= =front (n为数字角标的最大值)时,队为满.

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

循环队列实现

//循环队列
public class ArrayQueueLoop<E> implements Queue<E> {
    private E[] data;
    private int front;
    private int rear;
    private int size;
//无参构造函数
    public ArrayQueueLoop(){
        data= (E[]) (new Object[11]);//因为有一个空的空间
        front=0;
        rear=0;
        size=0;
    }
//获取长度
    @Override
    public int getSize() {
        return size;
    }
//判空
    @Override
    public boolean isEmpty() {
        return size==0&&front==rear;
    }
//进队
    @Override
    public void enqueue(E e) {
        if((rear+1)%data.length==front){
            resize(2*data.length-1);
        }
        data[rear]=e;
        rear=(rear+1)%data.length;
        size++;
    }
//出队
    @Override
    public E dequeue() {
        if(isEmpty()){
            throw new IllegalArgumentException("队列空");
        }
        E ret=data[front];
        front=(front+1)%data.length;
        size--;

        if(size<=(data.length-1)/4&&(data.length-1)/2>=10){
            resize((data.length-1)/2+1);
        }

        return ret;
    }
//改变数组长度    
    private void resize(int newLen){
        E[] newData= (E[]) (new Object[newLen]);
        int p=front;
        int i=0;
        while(true){
            newData[i]=data[p];
            i++;
            p=(p+1)%data.length;
            if(p==rear){
                break;
            }
        }
        front=0;
        rear=size;
        data=newData;
    }
//获取队头元素
    @Override
    public E getFront() {
        if(isEmpty()){
            throw new IllegalArgumentException("队列为空");
        }
        return data[front];
    }
//获取队尾元素
    @Override
    public E getRear() {
        if(isEmpty()){
            throw new IllegalArgumentException("队列为空");
        }
        return data[(rear-1+data.length)%data.length];
    }
//清空队列
    @Override
    public void clear() {
        data= (E[]) (new Object[11]);//因为有一个空的空间
        front=0;
        rear=0;
        size=0;
    }
//自定义格式打印元素
    @Override
    public String toString() {
        StringBuilder sb=new StringBuilder();
        sb.append(String.format("ArrayQueueLoop: %d/%d\n",size,data.length-1));
        sb.append('[');
        if(isEmpty()){
            sb.append(']');
        }else{
            for(int i=front;i!=rear;i=(i+1)%data.length){
                sb.append(data[i]);
                if((i+1)%data.length==rear){
                    sb.append(']');
                }else{
                    sb.append(',');
                }
            }
        }
        return sb.toString();
    }
    //迭代器
    @Override
    public Iterator<E> iterator() {
        return new ArrayQueueLoopIterator();
    }
    private class ArrayQueueLoopIterator implements Iterator{
        int p=front;
        @Override
        public boolean hasNext() {
            return p!=rear;
        }

        @Override
        public Object next() {
            E ret=data[p];
            p=(p+1)%data.length;
            return ret;
        }
    }
}

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
精心整理史上最全的数据结构flash演示动画,共5个版本,祝大家考研成功! \数据结构flash演示\版本1 \数据结构flash演示\版本2 \数据结构flash演示\版本3 \数据结构flash演示\版本4 \数据结构flash演示\版本5 \数据结构flash演示\版本1\1-4 算法和算法分析 冒泡排序.swf \数据结构flash演示\版本1\10-1-1插入排序.swf \数据结构flash演示\版本1\10-2-2直接插入排序.swf \数据结构flash演示\版本1\10-2-3折半插入排序.swf \数据结构flash演示\版本1\10-2-4-1直接插入排序.swf \数据结构flash演示\版本1\10-2-4表插入排序.swf \数据结构flash演示\版本1\10-2-5希尔排序.swf \数据结构flash演示\版本1\10-3-1起泡排序.swf \数据结构flash演示\版本1\10-3-2起泡排序.swf \数据结构flash演示\版本1\10-3-4快速排序.swf \数据结构flash演示\版本1\10-4-2堆排序大顶堆.swf \数据结构flash演示\版本1\10-4-3堆排序大顶堆.swf \数据结构flash演示\版本1\10-4-4堆排序建立堆.swf \数据结构flash演示\版本1\10-5-2归并排序.swf \数据结构flash演示\版本1\10-6-1多关键字排序.swf \数据结构flash演示\版本1\10-6-2分配收集.swf \数据结构flash演示\版本1\10-6-3分配收集2.swf \数据结构flash演示\版本1\10-6-4计数排序.swf \数据结构flash演示\版本1\2-2-1顺序表的查找.swf \数据结构flash演示\版本1\2-2-2顺序表的插入演示.swf \数据结构flash演示\版本1\2-2-3顺序表的插入算法.swf \数据结构flash演示\版本1\2-2-4顺序表的删除演示.swf \数据结构flash演示\版本1\2-2-5顺序表的删除算法.swf \数据结构flash演示\版本1\2-2-6.swf \数据结构flash演示\版本1\2-2-7.swf \数据结构flash演示\版本1\2-2-8.swf \数据结构flash演示\版本1\2-2-9.swf \数据结构flash演示\版本1\2-3-1.1单链表删除节点.swf \数据结构flash演示\版本1\2-3-1.2单链表插入节点.swf \数据结构flash演示\版本1\2-3-1单链表getElem.swf \数据结构flash演示\版本1\2-3-2单链表头插法.swf \数据结构flash演示\版本1\2-3-3.swf \数据结构flash演示\版本1\2-3-4.swf \数据结构flash演示\版本1\2-3-5带头结点的双向循环链表.swf \数据结构flash演示\版本1\2-3-6双向链表的插入.swf \数据结构flash演示\版本1\2-3-7双向链表的删除.swf \数据结构flash演示\版本1\2-3-8.swf \数据结构flash演示\版本1\2-3-9两个有序链表的连接.swf \数据结构flash演示\版本1\3-2-1栈的应用举例-进制转换.swf \数据结构flash演示\版本1\3-3-10链队列.swf \数据结构flash演示\版本1\3-3-11链队列-入队.swf \数据结构flash演示\版本1\3-3-12-1链队列出队.swf \数据结构flash演示\版本1\3-3-12-2链队列出队-队列空.swf \数据结构flash演示\版本1\3-3-13循环队列.swf \数据结构flash演示\版本1\3-3-1栈的应用举例-走迷宫-有解.swf \数据结构flash演示\版本1\3-3-2栈的应用举例-走迷宫-无解.swf \数据结构flash演示\版本1\3-3-4后缀式.swf \数据结构flash演示\版本1\3-3-5后缀式.swf \数据结构flash演示\版本1\3-3-6后缀式.swf \数据结构flash演示\版本1\3-3-7后缀式.swf \数据结构flash演示\版本1\3-3-9栈的应用举例-汉诺塔.swf \数据结构flash演示\版本1\3-4-1杨辉三角.swf \数据结构flash演示\版本1\3-4-2离散事件模拟.swf \数据结构flash演示\版本1\4-1-1串的定位操作.swf \数据结构flash演示\版本1\4-1-2串的替换.s
该资源包含了几乎所有的数据结构动画视频,帮助我们更好的理解数据结构与算法的编程思路。 目录如下: 'B树的删除.swf', 'B树的生长过程.swf', '三元组表的转置.swf', '中序线索化二叉树.swf', '串的顺序存储.swf', '二分查找.swf', '二叉排序树的删除.swf', '二叉排序树的生成.swf', '二叉树的建立.swf', '克鲁斯卡尔算法构造最小生成树.swf', '冒泡排序.swf', '分块查找.swf', '单链表结点的删除.swf', '单链表结点的插入.swf', '图的深度优先遍历.swf', '基数排序.swf', '堆排序.swf', '头插法建单链表.swf', '寻找中序线索化二叉树指定结点的前驱.swf', '寻找中序线索化二叉树指定结点的后继.swf', '尾插法建表.swf', '希儿排序.swf', '开放定址法建立散列表.swf', '归并排序.swf', '循环队列操作演示.swf', '快速排序.swf', '拉链法创建散列表.swf', '拓扑排序.swf', '最短路径.swf', '朴素串匹配算法过程示意.swf', '构造哈夫曼树的算法模拟.swf', '构造哈夫曼树过程.swf', '栈与递归.swf', '树、森林和二叉树的转换.swf', '桶式排序法.swf', '直接插入排序.swf', '直接选择排序.swf', '邻接表表示的图的广度优先遍历.swf', '邻接表表示的图的深度优先遍历.swf', '顺序查找.swf', '顺序栈(4个存储空间).swf', '顺序栈(8个存储空间).swf', '顺序表的删除运算.swf', '顺序表的插入.swf', '顺序队列操作.swf'。 (注:.swf动画格式可直接使用播放器打开。)
顺序循环队列是一种使用顺序存储结构实现的队列。它通过将队列的首尾相连,构成一个循环的结构,解决了普通队列在出队操作时需要移动元素的问题,提高了算法效率。[2] 顺序循环队列的结构定义如下: ```c #define SIZE 8 typedef struct Queue { int elem[SIZE]; // 存放队列元素 int front; // 队头 int rear; // 队尾 } Queue, *QueueS; ``` 其中,`elem`数组用于存放队列元素,`front`表示队头的位置,`rear`表示队尾的位置。当队列为空时,`front`和`rear`的值相等;当队列满时,`rear`的下一个位置就是`front`。通过这种方式,可以实现循环利用队列的存储空间。 顺序循环队列的操作包括入队和出队操作。入队操作将元素插入到队尾,同时更新`rear`的位置;出队操作将队头元素删除,同时更新`front`的位置。当队列满时,无法进行入队操作;当队列为空时,无法进行出队操作。因此,需要额外的判断条件来判断队列是否满或为空。 顺序循环队列的实现可以通过取模运算来实现循环的效果,即在计算`rear`和`front`的位置时,使用`(rear + 1) % SIZE`和`(front + 1) % SIZE`来计算新的位置。 总结来说,顺序循环队列是一种通过循环利用队列存储空间来提高算法效率的数据结构。它使用顺序存储结构实现,通过将队列的首尾相连构成循环结构,解决了普通队列在出队操作时需要移动元素的问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值