泛型动态循环队列的实现——Java

岁酱吖の 提交于 2020-01-31 11:39:41

队列的基本功能

public interface Queue<E> {
    void enqueue(E e);//元素入队
    E dequeue();//元素出队
    E getFront();//查看队头
    int getSize();//存储了多少数据
    boolean isEmpty();
}

如何实现

使用数组存储数据,front存储队头元素的下标,tail存储队尾元素下一个元素的下标,元素入队,tial前移,元素出队,front前移。

front=tail时队列为空,front在tail前一格时队列满。(浪费了tail所指的空间,目的是更容易区分空和满两种情况,这样:队列容量=数组长度-1)。

代码

public class ArrayQueue<E> implements Queue<E> {
    private E[] data;
    private int front,tail;//指向队首元素
    private int size;//指向队尾元素下一个位置,即下一个元素的位置

    public ArrayQueue(int capacity){//*泛型类构造函数类名后不加<>
        data=(E[])new Object[capacity+1];//数组长度比容量大1
        front=tail=size=0;
    }
    public ArrayQueue(){
        this(10);//
    }

    private void resize(int capacity){
        if(capacity<2) return;//最多缩容到2
        E[] newData=(E[])new Object[capacity];
        for(int i=0;i<size;i++){
            newData[i]=data[(i+front)%data.length];
            //**循环front到tail的数据,拷贝到新数组
        }
        data=newData;
        front=0;
        tail=size;
    }

    @Override
    public void enqueue(E e){
        if(size+1>this.getCapacity()){//容量不足
            resize(getCapacity()*2);//不可以使用data.length
        }
        data[tail]=e;
        tail=(tail+1)%data.length;
        size++;
    }

    @Override
    public E dequeue(){
        E ret=data[front];
        if(size!=0){
            data[front]=null;//便于垃圾回收
            front=(front+1)%data.length;
            size--;
        }
        else{
            throw new IllegalArgumentException("不能从空队列中取值");
        }
        if(size<=getCapacity()/4){
            resize(getCapacity()/2);
        }//*如果容量过大,进行缩容
        return ret;
    }

    @Override
    public E getFront(){
        if(size==0)
            throw new IllegalArgumentException("不可从空队列中取队首值");
        else
            return data[front];
    }

    public int getCapacity(){
        return  data.length-1;
    }

    @Override
    public boolean isEmpty(){
        return tail==front;
    }

    @Override
    public int getSize(){
        return size;
    }

    @Override
    public String toString(){
        StringBuilder res=new StringBuilder();
        res.append("size:"+size+" capacity"+this.getCapacity()+" front"+front+" tail"+tail+"\n");
        res.append("front[");
        for(int i=front;i!=tail;i=(i+1)%data.length){
            res.append(data[i]);
        }//循环从front到tail的数据
        res.append("]tail");
        return res.toString();
    }
}

可以看到获取从front到tail的数据有两种方法:

for(int i=0;i<size;i++){
	System.out.println(data[(front+i)%data.length]);
}
for(int i=front;i!=tail;i=(i+1)%data.length){
	System.out.println(data[i]);
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!