数据结构之数组实现循环队列两种方式

使用数组实现循环队列,这里实现了add和poll两个关键接口

普通数组实现队列时,数组末端元素占满后需要检查首端是否占满,若未占满进行整体向前复制,若都占满则进行扩容;
循环队列优势在于仅在扩容时才进行数组复制操作,其余仅仅是根据tail索引添加元素,但会使用一个多余空间记录下一次添加时的索引,这样很好理解当first=tail时队列为空。
/**
 * 数组实现循环队列普通方式
 *
 * 若使用first和last记录队首和队尾元素所在索引,当first=last时无法区分存在一个元素还是队列为空,需要增加size记录元素个数才能实现队列。
 * 数组实现的普通队列添加一个元素后,first=0,下一个元素索引tail=1表明数组中存在一个元素,当first=0,tail=0时数组为空。
 * 所以tail作为下一个元素的索引永远会占一个空间
 * 循环队列同理,必须使用tail占用下一个元素的位置当first=tail时说明最后一个元素已经被取出或者未添加,则数组为空。
 * 
 * @date: 2021/3/27 22:31
 * @author: JiGang Q
 */
public class MyCircleQueue<T> implements MyQueue<T> {

    private Object[] elements;
    private static final int MIN_INITIAL_CAPACITY = 8;
    private int first; //第一个元素
    private int tail; //下次将要操作的索引,会在每次添加赋值后向“后”移动

    public MyCircleQueue() {
        this(MIN_INITIAL_CAPACITY + 1);
    }

    public MyCircleQueue(int size) {
        if (size <= 0)
            throw new IllegalArgumentException("size is not less than 0");
        elements = new Object[size];
    }

    @Override
    public boolean add(T t) {
        elements[tail] = t;
        //末端扩容
        if (tail + 1 == elements.length) {
            if (first == 0) {
                //正常扩容
                Object[] newArr = new Object[elements.length<<1];
                System.arraycopy(elements,0,newArr,0, elements.length);
                elements = newArr;
                tail++;
            } else {
                tail = 0;
            }
        }else if (tail + 1 == first) {
            //中间扩容,还有种思路是放后面
            Object[] newArr = new Object[elements.length<<1];
            System.arraycopy(elements, first, newArr,0, elements.length - first);
            System.arraycopy(elements,0,newArr,elements.length - first, first);
            first = 0;
            tail = elements.length;
            elements = newArr;
        } else {
            tail++;
        }
        return true;
    }

    @Override
    public T poll() {
        if (first == tail)
            return null;
        T e = (T) elements[first];
        elements[first] = null;
        if (first == elements.length - 1)
            first = 0;
        else
            first++;
        return e;
    }

    @Override
    public String toString() {
        if (first == tail)
            return "[]";
        StringBuilder builder = new StringBuilder();
        builder.append("[");
        if (first < tail) {
            for (int i = first; i < tail; i++)
                builder.append(elements[i].toString() + ",");
        } else {
            for (int i = first; i < elements.length; i++)
                builder.append(elements[i].toString() + ",");
            for (int i = 0; i < tail; i++)
                builder.append(elements[i].toString() + ",");
        }
        String str = builder.toString();
        return str.substring(0,str.length() - 1) + "]";
    }

}

使用求模实现循环队列
/**
 *
 * 使用求模实现队列
 *
 * @date: 2021/3/28 0:57
 * @author: JiGang Q
 */
public class CircleQueue<T>  implements MyQueue<T>  {

    private Object[] elements;
    private static final int MIN_INITIAL_CAPACITY = 8;
    private int first;
    private int tail;

    public CircleQueue() {
        this(MIN_INITIAL_CAPACITY + 1);
    }

    public CircleQueue(int size) {
        if (size <= 0)
            throw new IllegalArgumentException("size is not less than 0");
        elements = new Object[size];
    }

    @Override
    public boolean add(T t) {
        elements[tail] = t;
        grow();
        tail = (tail+1)%elements.length;
        return true;
    }

    //扩容
    private void grow() {
        if ((tail+1)%elements.length == first) {
            Object[] newArr = new Object[elements.length<<1];
            for (int i = 0; i < elements.length; i++)
                newArr[i] = elements[(i + first)%elements.length];
            tail = elements.length - 1;
            elements = newArr;
            first = 0;
        }
    }

    @Override
    public T poll() {
        if (first == tail)
            return null;
        T e = (T) elements[first];
        elements[first] = null;
        first = (first + 1)%elements.length;
        return e;
    }

    @Override
    public String toString() {
        if (first == tail)
            return "[]";
        StringBuilder builder = new StringBuilder();
        builder.append("[");
        for (int i = first; i != tail; i = (i + 1)%elements.length) {
            builder.append(elements[i].toString() + ",");
        }
        String str = builder.toString();
        return str.substring(0,str.length() - 1) + "]";
    }


}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值