队列知识总结

栈(Stack)和队列(Queue)的相同点和不同点是什么?如何用两个栈实现队列(入队和出队)?

  • 相同点:

    • 栈和队列都属于线性表
    • 栈和队列插入操作都是限定在线性表的头尾进行
    • 栈和队列插入和删除的时间复杂度是O(1)
  • 不同点:

    • 特性不同,栈先进后出 (LIFO,Last In First Out) ;队列先进先出 (FIFO,First In First Out)
    • 栈知识表的一端进行插入和删除操作,队列是在表的一端插入,另一端删除
    • Java的栈(Stack)继承自 Vector,再往上的接口是 List/Collection;队列(Queue)直接继承自Collection接口
  • 栈实现队列:

    /**
     * 两个栈组成队列
     */
    public class StackQueue<E> {
        //入队操作的栈
        private Stack<E> stack1 =new Stack<>();
        //出队操作的栈
        private Stack<E> stack2 =new Stack<>();
    
    
        /**
         * 压入队列元素,只使用stack1
         * @param element
         */
        public void push(E element) {
            stack1.add(element);
        }
    
        /**
         * 取出队列顶部元素
         * @return
         */
        public E poll() {
            // stack2的数据为空时,才把stack1中的元素压入stack2(两种情况:1、初始化时两个栈的数据均为空;2、stack2数据出栈出完了
            if (stack2.isEmpty()) {
                while (stack1.size() > 0) {
                    stack2.add(stack1.pop());
                }
            }
            //stack1的数据出栈完成后,stack2仍然为空,说明两个栈的数据都为空
            if (stack2.isEmpty()) {
                throw new RuntimeException("queue is Empty!");
            }
            E head = stack2.pop();
            return head;
        }
    }
    
  • 队列实现栈:

    class MyStack {
    
        Queue<Integer> queue;
        
        /** Initialize your data structure here. */
        public MyStack() {
            queue = new LinkedList<>();
        }
        
        /** Push element x onto stack. */
        public void push(int x) {
            queue.add(x);
            for (int i = 1; i < queue.size(); i++) {
                queue.add(queue.remove());
            }
        }
        
        /** Removes the element on top of the stack and returns that element. */
        public int pop() {
            return queue.poll();
        }
        
        /** Get the top element. */
        public int top() {
            return queue.peek();
        }
        
        /** Returns whether the stack is empty. */
        public boolean empty() {
            return queue.size() == 0;
        }
    
    }
    
  • 队列都属于线性表(linear list),而线性表是 n 个具有相同特性的数据元素的有限序列

Queue及常用子类可分三类:

图片描述

  • 双端队列(Deque):头部和尾部都支持插入和获取
  • 阻塞队列(BlockingQueue):在元素的添加/删除操作时,如果没有成功,会阻塞等待执行。例如:当添加元素时,如果队列元素已满,队列会阻塞等待直到有空位时再插入
  • 非阻塞队列(Non BlockingQueue):在元素的添加/删除操作时,如果没有成功,会直接返回操作的结果(通常双端队列也属于非阻塞队列)
  • 常见的Queue的特性:
    • PriorityBlockingQueue:带优先级的无界阻塞队列,元素按优先级顺序被移除,而不是先进先出队列(FIFO)。此外,队列中的元素要具有比较能力(用于判定优先级)。PriorityBlockingQueue 不允许 null 元素
    • DelayQueue:存放 Delayed 元素的无界阻塞队列,只有在延迟期满时才能从中提取元素。该队列的头部是延迟期满后保存时间最长的 Delayed 元素。如果延迟都还没有期满,则队列没有头部,DelayQueue 不允许使用 null 元素
    • SynchronousQueue:同步阻塞队列,它的每个插入操作都要等待其他线程相应的移除操作,反之亦然。它的一个典型应用场景是 Executors.newCachedThreadPool () ,在新任务到来时创建新的线程,如果有空闲线程则会重复使用,SynchronousQueue 不允许 null 元素

LinkedHashMap和PriorityQueue的区别?

  • PriorityQueue 是一个优先级队列,保证最高或者最低优先级的的元素总是在队列头部,但是 LinkedHashMap 维持的顺序是元素插入的顺序。当遍历一个 PriorityQueue 时,没有任何顺序保证,但是 LinkedHashMap 课保证遍历顺序是元素插入的顺序

Queue中add/offer方法的区别?

  • add()和offer()都是向队列中添加一个元素。一些队列有大小限制,因此如果想在一个满的队列中加入一个新项,调用 add() 方法就会抛出IllegalStateException异常,而调用 offer() 方法会返回 false

Queue中remove()/poll()方法的区别?

  • poll()/remove()方法都是从队列中删除头部元素。如果队列元素为空,调用remove() 则会抛出NoSuchElementException,而poll() 方法在用空集合调用时只是返回 null。

Queue中element()/peek()方法的区别?

  • element() 和 peek() 用于在队列的头部查询元素。与 remove() 方法类似,在队列为空时, element() 抛出NoSuchElementException异常,而 peek() 返回 null

BlockingQueue有哪些实现类?ArrayBlockingQueue: 由数组组成的有界阻塞队列?

  • LinkedBlockingQueue: 由链表组成的有界阻塞队列(默认大小为 Integer.MAX_VALUE)
  • PriorityBlockingQueue:支持优先级排序的无界阻塞队列
  • DelayQueue:使用优先级队列实现的延迟无界阻塞队列
  • SynchronousQueue: 不存储元素的阻塞队列,单个元素的队列,同步提交队列
  • LinkedTransferQueue:链表组成的无界阻塞队列
  • LinkedBlockingDeque:链表组成的双向阻塞队列

文章推荐:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值