Queue中的Deque

199 阅读2分钟

声明

从源码入手分析Deque接口的特征以及其部分实现类的特点,从迭代遍历二叉树、层次遍历二叉树实践阐释Deque的用处。

源码部分

/*
Deque,发音为“Deck”,继承于Queue,所以拥有Collections接口的方法,是一个双端队列,既涵盖了队列的基本特征又具有栈的基本特征。元素进出容器都保持后进先出的逻辑机制。
*/
public interface Deque<E> extends Queue<E> 
{
    //接口提供insert/remove/examine三类方法
    //insert methods
    //collections: add
    //queue: offer offerFirst offerLast addFirst addLast
    //stack: push 
    
    //remove methods
    //collections: remove 
    //queue: poll removeLast removeFirst pollLast  pollFirst
    //stack: pop  
    
    //examine methods
    //collections: 
    //queue: getLast getFirst peek peekLast peekFirst
    //stack: peek
}

因为Deque也是一个接口,所以下面具体分析其实现类ArrayDeque和继承接口BlockingDeque下的实现类LinkedBlockingDeque

package java.util.concurrent;

import java.util.AbstractQueue;
import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.Consumer;
/*
LinkedBlockingDeque最大的特征是用Lock锁保证其安全性,用双向指针结点实现其数据结构。同时也要注意的是此类实在JUC包下,JDK1.6后才有的。
*/
public class LinkedBlockingDeque<E> extends AbstractQueue<E> implements BlockingDeque<E>,java.io.Seriablizable
{
    //静态内部类Node
    static final class Node<E>{
        E item;
        Node<E> prev;
        Node<E> next;
        Node(E x){
            item = x; 
        }
        transient Node<E> first;
        transient Node<E> last;
        /*  保护所有通道的主锁  */
        final ReentrantLock lock  = new ReentranLock();
        
        /*  等待条件  */
        private final Condition notFull = lock.newCondition();
        /*  等待条件  */
        private final Condition notEmpty = lock.newCondition();
        //剩余代码都是具体方法和如何实现的算法呢,至于ReentrantLock、Condition不懂,等我!
    }
}
/*
ArrayDeque是线程不安全的,ArrayList不也是这样嘛。
使用数组实现数据结构
*/
public class ArrayDeque<E> extends AbstractCollection<E>
                           implements Deque<E>, Cloneable, Serializable
{
    transient Object[] elements;
    transient int head;
    transient int tail;
    
    public ArratDeq{
        /* 默认空参构造 数组长度为16 */
        elements = new Object[16];
    }
}

可以看出来,Deque具体实现类就是围绕着数组、链表,线程安全/不安全来具体分类的。当然,Deque接口还有不少来自JUC包下的实现类,这不做深究。

写题时的实用

/*
@ClassName IterationTreeNodeTest
@Description TODO
@Author SubUp
@Date   2022/7/18
@Version 1.0
*/

package com.degisn.ddd.exercise;

import org.junit.Test;

import java.util.*;
import java.util.concurrent.LinkedBlockingQueue;

public class IterationTreeNodeTest {
    public TreeNode generateTreeNode(){
        /**
         *      12
         *    21   2
         *   32
         */
        TreeNode root = new TreeNode(12);
        TreeNode root1 = new TreeNode(21);
        TreeNode root2 = new TreeNode(32);
        TreeNode root3 = new TreeNode(2);
        root.left = root1;
        root.right = root3;
        root1.left = root2;
        return root;
    }
    
    /*迭代遍历二叉树*/
    
    /* 前序遍历 */
    @Test
    public void qianTest(){
        /* 生成二叉树 */
        TreeNode root = generateTreeNode();
        Stack<TreeNode> stack = new Stack();
        Vector<Integer> vc = new Vector<>();
        if(root == null)
            System.out.println("null");
        stack.push(root);
        while (!stack.isEmpty()){
            TreeNode node = stack.pop();
            vc.add(node.val);
            if(node.right != null)
                stack.push(node.right);
            if(node.left != null)
                stack.push(node.left);

        }
        System.out.println(vc);
    }
    //中序遍历,先找到第一个结点这个过程把不为null的结点全都入栈
    //当找到最左的结点后即他的左子节点为null把他的值加入到容器中,然后去获得其右子节点
    @Test
    public void zhongTest(){
        TreeNode root = generateTreeNode();
        Stack<TreeNode> stack = new Stack();
        Vector<Integer> vc = new Vector<>();
        while (root!=null || !stack.isEmpty()){
            if(root != null){
                stack.push(root);
                root = root.left;
            }else{
                TreeNode dump = stack.pop();
                vc.add(dump.val);
                root = dump.right;
            }
        }
        System.out.println(vc);
    }

    //后序遍历
    @Test
    public void houTest(){
        TreeNode root = generateTreeNode();
        Stack<TreeNode> stack = new Stack();
        Vector<Integer> vc = new Vector<>();
        if(root == null)
            System.out.println("null");
        stack.push(root);
        while (!stack.isEmpty()){
            TreeNode node = stack.pop();
            if(node.right != null)
                stack.push(node.right);
            if(node.left != null)
                stack.push(node.left);
            vc.add(node.val);

        }
        System.out.println(vc);
    }

    /* 层次遍历二叉树 */
    @Test
    public void levelTest(){
        System.out.println("层次遍历二叉树");
        TreeNode root = generateTreeNode();
        Deque<TreeNode> dq = new ArrayDeque<>();
        Vector<Integer> vc = new Vector<>();
        if(root == null)
            System.out.println(root);
        dp.offer(root);
        while(!dp.isEmpty()){
            int doCount = dp.size();
            for (int i = 0; i <doCount ; i++) {
                TreeNode node = dp.poll();
                if(node.right != null)
                    dp.offer(node.right);
                if(node.left != null)
                    dp.offer(node.left);
                vc.add(node.val);
            }
        }
        System.out.println(vc);
    }
    @Test
    public void ReverseListLevelTest(){
        System.out.println("从叶子节点所在层到根节点所在的层,逐层从左向右遍历");
        TreeNode root = generateTreeNode();
        List<List<Integer>> rt = new ArrayList<>();
        Deque<TreeNode> qe = new ArrayDeque<>();

        if(root == null)
            System.out.println("---null");
        qe.offer(root);
        while (!qe.isEmpty()){
            int stackCount = qe.size();
            List<Integer> list = new ArrayList<>();
            for (int i = 0; i <stackCount ; i++) {
                TreeNode node = qe.poll();
                if(node.left != null)
                    qe.offer(node.left);
                if(node.right != null)
                    qe.offer(node.right);
                list.add(node.val);
            }
            rt.add(0,list);
        }
        System.out.println(rt);
    }
}