Java数据结构:队列(1)

 

1、队列

栈是一种先进后出线性数据结构,数据的插入和删除只能在一端操作。

队列是一种先进先出线性数据结构,队尾一端插入数据,队头一端删除数据。

2、单向队列的实现:

与基于数组的栈不同的是,基于数组实现的队列在出队操作时,相当于删除数组下标为 0 的数据,要搬移整个队列中的数据。

/**
 * description: 基于数组实现队列
 * date: 2019/8/21
 * author: wp
 */
public class MyQueue {

    /**
     * 容器
     */
    private Object[] elementData;

    /**
     * 队列的默认大小
     */
    private static final int DEFAULT_SIZE = 10;

    /**
     * 队列中元素个数
     */
    protected int elementCount;

    /**
     * 默认构造器
     */
    public MyQueue() {
        this(DEFAULT_SIZE);
    }

    /**
     * 指定队列的容量构造器
     */
    public MyQueue(int size) {
        if (size < 0) {
            throw new RuntimeException();
        }
        elementData = new Object[size];
    }


    /**
     * 入队操作
     * 将指定的元素插入此队列,(如果违反容量限制抛出IllegalStateException)
     *
     * @param obj
     * @return
     */

    public synchronized boolean add(Object obj) {
        if (isFull()) {
            //栈满了,需要扩容
            throw new IllegalStateException();
        }
        elementData[elementCount] = obj;
        elementCount++;
        return true;
    }

    /**
     * 入队操作
     * 将指定的元素插入此队列,(如果违反容量限制不抛异常)
     *
     * @param obj
     * @return
     */
    public synchronized boolean offer(Object obj) {
        if (isFull()) {
            //栈满了,需要扩容
            Object[] temp = elementData;
            elementData = new Object[elementData.length * 2];
            System.arraycopy(temp, 0, elementData, 0, temp.length);
        }
        elementData[elementCount] = obj;
        elementCount++;
        return true;
    }

    /**
     * 出队操作
     * 获取但不移除, 如果此队列为空,则返回 null
     *
     * @return
     */
    public Object peek() {
        if (!isEmpty()) {
            return elementData[0];
        }
        return null;
    }

    /**
     * 出队操作
     * 获取但不移除, 如果此队列为空,则返回 null,如果此队列为空,则将抛出NoSuchElementException异常
     *
     * @return
     */
    public synchronized Object element() {
        if (isEmpty()) {
            throw new NoSuchElementException();
        }
        return elementData[0];

    }

    /**
     * 出队操作
     * 获取并移除, 如果此队列为空,则返回 null
     *
     * @return
     */
    public synchronized Object poll() {
        if (isEmpty()) {
            return null;
        }
        Object obj = peek();
        //左移数组
        leftMove(elementData,1);
        elementCount--;
        return obj;

    }


    /**
     * 出队操作
     * 获取并移除,如果此队列为空,则抛出NoSuchElementException异常
     *
     * @return
     */
    public synchronized Object remove() {
        if (isEmpty()) {
            throw new NoSuchElementException();
        }
        Object obj = peek();
        //左移数组
        leftMove(elementData,1);
        elementCount--;
        return obj;

    }


    /**
     * 判断队列是否为空
     */
    public boolean isEmpty() {
        return elementCount == 0;
    }

    /**
     * 判断队列是否已满
     */
    public boolean isFull() {
        return elementCount == elementData.length;
    }

    /**
     * 数组所有元素左移动x位
     *
     * @param arr
     */
    public void leftMove(Object[] arr, int x) {
        for (int i = 0; i < arr.length; i++) {
            if (i >= arr.length - x) {
                arr[i] = null;
                continue;
            }
            arr[i] = arr[i + x];
        }
    }

    @Test
    public void test() {
        MyQueue queue = new MyQueue();
        for (int i = 0; i < 70; i++) {
            queue.offer("data" + i);
        }
        for (int i = 0; i < 70; i++) {
            System.out.println(queue.poll());
        }
    }
}

 

3、基于数组的单向队列优化方案

因为出队操作都相当于删除数组下标为 0 的数据,要搬移整个队列中的数据,这样出队操作的时间复杂度就会从原来的 O(1) 变为 O(n)。

优化方案,维护两个指针,一个是 head 指针,指向队头;一个是 tail 指针,指向队尾。出队时可以不用搬移数据。如果没有空闲空间了,我们只需要在入队时,再集中触发一次数据的搬移操作。

/**
 * description: 基于数组实现队列(基于头尾指针维护队列)
 * date: 2019/8/21
 * author: wp
 */
public class MyQueue {

    /**
     * 容器
     */
    private Object[] elementData;

    /**
     * 队列的默认大小
     */
    private static final int DEFAULT_SIZE = 10;

    /**
     * 队列中头指针
     */
    private int head;

    /**
     * 队列中尾指针
     */
    private int tail;

    /**
     * 默认构造器
     */
    public MyQueue() {
        this(DEFAULT_SIZE);
    }


    /**
     * 指定队列的容量构造器
     */
    public MyQueue(int size) {
        if (size < 0) {
            throw new RuntimeException();
        }
        elementData = new Object[size];
    }


    /**
     * 入队操作
     * 将指定的元素插入此队列,(如果违反容量限制抛出IllegalStateException)
     *
     * @param obj
     * @return
     */

    public synchronized boolean add(Object obj) {
        if (isFull()) {
            //队列满了
            throw new IllegalStateException();
        }
        elementData[tail] = obj;
        tail++;
        return true;
    }

    /**
     * 入队操作
     * 将指定的元素插入此队列,(如果违反容量限制不抛异常)
     *
     * @param obj
     * @return
     */
    public synchronized boolean offer(Object obj) {
        //队列满了
        if (isFull()) {
            //这时候集中删除触发一次数据搬移
            if (head > 0) {
                leftMove(elementData, head);
                tail = tail - head;
                head = 0;
            } else {
                Object[] temp = elementData;
                elementData = new Object[elementData.length * 2];
                System.arraycopy(temp, 0, elementData, 0, temp.length);
            }
        }
        elementData[tail] = obj;
        tail++;
        return true;
    }

    /**
     * 出队操作
     * 获取但不移除, 如果此队列为空,则返回 null
     *
     * @return
     */
    public Object peek() {
        if (!isEmpty()) {
            return elementData[head];
        }
        return null;
    }

    /**
     * 出队操作
     * 获取但不移除, 如果此队列为空,则返回 null,如果此队列为空,则将抛出NoSuchElementException异常
     *
     * @return
     */
    public synchronized Object element() {
        if (isEmpty()) {
            throw new NoSuchElementException();
        }
        return elementData[head];

    }

    /**
     * 出队操作
     * 获取并移除, 如果此队列为空,则返回 null
     *
     * @return
     */
    public synchronized Object poll() {
        if (isEmpty()) {
            return null;
        }
        Object obj = peek();
        //头指针后移一位
        head++;
        return obj;

    }


    /**
     * 出队操作
     * 获取并移除,如果此队列为空,则抛出NoSuchElementException异常
     *
     * @return
     */
    public synchronized Object remove() {
        if (isEmpty()) {
            throw new NoSuchElementException();
        }
        Object obj = peek();
        //头指针后移一位
        head++;
        return obj;

    }


    /**
     * 判断队列是否为空
     */
    public boolean isEmpty() {
        return head == tail;
    }

    /**
     * 判断队列是否已满
     */
    public boolean isFull() {
        return tail == elementData.length;
    }


    /**
     * 数组所有元素左移动x位
     *
     * @param arr
     */
    public void leftMove(Object[] arr, int x) {
        for (int i = 0; i < arr.length; i++) {
            if (i >= arr.length - x) {
                arr[i] = null;
                continue;
            }
            arr[i] = arr[i + x];
        }
    }
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值