数据结构------循环队列

循环队列

队列的顺序结构本身是由ArrayList实现的

在数据元素入队的时候,相当于在ArrayList表尾添加元素

在数据元素出队的时候,相当于在ArrayList表头删除元素

很明显,入队的时间复杂度O(1),出队的时间复杂度是O(n)

但是线性表的增删数据元素时间复杂度都是O(n),但是这个是按平均算的

优化一:

能否让队头指针和队尾指针一样随着数据元素的变化而变化呢

循环队列ArrayLoopQueue(该循环队列的实现思想是动态数组),但是由于操作元素的特殊性,并不能直接由ArrayList和ArrayQueue实现,所以从头开始定义ArrayLoopQueue

优化2:
队尾或者队头指针到达尾部,如需后移可以重新指向表头(可以继续循环)

优化三:

将一个空间留出来,专门放尾部指针

 ArrayLoopQueue类

package 动态数组;

import 接口.Queue;

import java.util.Iterator;

public class ArrayLoopQueue<E> implements Queue<E> {
    //定义队列默认的容量
    private static int DEFAULT_CAPACITY;
    //定义头指针
    private int front;
    //定义尾指针
    private int rear;
    //定义队列的有效元素的个数
    private int size;
    //定义队列的容器
    //如果front==rear表示队列已空,
    //如果(rear+1)%data.length==front表示队列已满
    private E [] data;
    //创建用户指定容量的队列
    public ArrayLoopQueue(int capacity){
        //加一是因为留一个空位置专门放尾指针
        data =(E [])new Object[capacity+1];
        front =0;
        rear =0;
        size =0;
    }
   //创建系统默认的容量的容器
    public ArrayLoopQueue(){
        this(DEFAULT_CAPACITY+1);
    }
    //获取循环队列有效元素的个数
    @Override
    public int size() {
        return size;
    }
//判断循环队列是否为空
    @Override
    public boolean isEmpty() {
        return size==0&&front==rear;
    }
       //向循环队列中入队一个元素
    @Override
    public void offer(E element) {
       data[rear]=element;
//表示下一个rear的位置,因为不能写成rear+1,因为这是一个循环的队列,所以用(rear+1)%data.length
       rear=(rear+1)%data.length;
       size++;
       //判断是否需要扩容
        if((rear+1)%data.length==front){
            减一是因为我们要达到21的效果
            resize(data.length*2-1);
        }
    }
  //扩容
    private void resize(int len) {
        E [] newData =(E [])new Object[len];
        int index=0;
        for(int i=front;i!=rear;i=(i+1)%data.length){
            newData[index++]=data[i];
        }
        //首尾指针需要重新改变
        front=0;
        rear=index;
        data=newData;
    }
//循环队列出队一个元素
    @Override
    public E poll() {
        if(isEmpty()){
            throw new NullPointerException("队列是空的");
        }
        E ret =data[front];
        front =(front+1)%data.length;//表示下一个元素的位置
        size--;
        //判断是否要进行缩容
        if(size==(data.length-1)/4&&data.length-1>DEFAULT_CAPACITY){
            resize(data.length/2+1);
        }
        return ret;
    }

    @Override
    public E element() {
        if(isEmpty()){
            throw new NullPointerException("队列是空的");
        }
        return data[front];
    }

    @Override
    public void clear() {
        data =(E [])new Object[DEFAULT_CAPACITY+1];
        front =0;
        rear =0;
        size =0;
    }
    //重写toString()函数
    public String toString(){
        StringBuilder sb =new StringBuilder(String.format("ArrayLoopQueue:%d/%d[",size,data.length));
        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 ArrayLoopQueueIterator();
    }
    class ArrayLoopQueueIterator implements Iterator<E>{
             //设置游标
           private int cur=0;
        @Override
        public boolean hasNext() {
            return cur!=rear;
        }

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

测试类

package 动态数组;

public class TestArrayLoopQueue {
    public static void main(String[] args) {
        ArrayLoopQueue<Integer> loopQueue =new ArrayLoopQueue<>();
        for(int i=0;i<=12;i++){
            loopQueue.offer(i);
        }
        System.out.println(loopQueue);
    }
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值