学习数据结构不得不看的队列知识

你可以插秧,插花,插班,但不可以插队。

泱泱中华,礼仪大邦。无论在车站等车、去食堂打饭、去景点买门票等等,自觉排队已成为一个人的基本道德体现,井然有序的队列在生活中随处可见,今天忘忧跟大家一起讨论下程序世界的队列。

什么是队列

队列,是一种比较基础的数据结构,它属于线性数据结构中比较特殊的一种,他的特殊在于元素的进出受到了一定规则的限制,它需要时刻遵守先进先出(FIFO)的规则。即在买票过程中,越早进入队列的人越早买到票。

队列的实现

队列可以按照存储方式分为两种实现方式。
一种是基于数组实现的定长队列,它的长度取决于数组的长度。
另一种是基于列表实现的不定长队列,理论上可以无限长。

首先,使用接口定义队列应有的基本方法,代码如下:

/**
 * algorithm
 * @author 忘忧
 * @date 2020/3/13
 * 定义队列的基本方法
 */
public interface Queue {

    /**
     * 获取当前队列的长度
     * @return 当前队列长度
     */
    int size();

    /**
     * 判断当前队列是否已满
     * @return 当前队列是否已满
     */
    boolean isFull();

    /**
     * 元素出队
     * @return 出队元素
     * @throws QueueEmptyException 队列空时跑出该异常
     */
    Object remove() throws QueueEmptyException;

    /**
     * 元素入队
     * @param t 入队元素
     * @throws QueueFullException 当队列满时抛出该异常
     */
    void insert(Object t) throws QueueFullException;
}

基于数组实现的队列

思路:使用两个索引分别标记队列队首和队尾的位置。
队首元素出队时,将队首元素后移(如果后移后数组越界,则将队首元素置为0)。
新元素入队时,将队尾元素后移(如果后移后数组越界,则将队尾元素置为0)。

![](

基于数组的代码实现:


/**
 * algorithm
 * @author 忘忧
 * @date 2020/3/13
 * 队列相关知识
 */
public class ArrayQueue implements Queue {

    private Object[] elements;

    /**
     * 队首元素位置
     */
    private int headIndex = 0;

    /**
     * 队尾元素索引
     */
    private int tailIndex = 0;

    private int size = 0;

    /**
     * 初始化数组
     * @param capacity 容量
     */
    public ArrayQueue(int capacity) {
        this.elements = new Object[capacity];
    }

    @Override
    public int size() {
        return this.size;
    }

    @Override
    public boolean isFull() {
        return this.size() == elements.length;
    }

    /**
     * 队首元素出队
     * @return 队首元素
     * @throws QueueEmptyException 空队异常
     */
    @Override
    public Object remove() throws QueueEmptyException {
        if(this.size() == 0){
            throw new QueueEmptyException();
        }
        size--;
        Object element = elements[headIndex++];
        if(headIndex == elements.length){
            headIndex = 0;
        }
        return element;
    }

    /**
     * 新元素入队
     * @param element 新元素
     * @throws QueueFullException 满队异常
     */
    @Override
    public void insert(Object element) throws QueueFullException {
        if(isFull()){
            throw new QueueFullException();
        }
        size++;
        elements[tailIndex++] = element;
        if(tailIndex == elements.length){
            tailIndex = 0;
        }
    }
}

基于链表实现的队列

思路:使用两个指针,分别标示头尾节点。
新增元素时,将尾节点的next置为新增节点,然后尾节点后移一位。
移除队首元素时,头节点后移一位。
需要留意的是,新增第一个元素和第二个元素需要特殊处理

  • 由于新增第一个元素前,当前的头节点是null,需要将头节点设置为新增的节点
  • 新增第二个节点时,由于头节点的next是null,需要将第二个节点设置为头节点的next)

/**
 * algorithm
 * @author 忘忧
 * @date 2020/3/14
 * 基于链表实现的队列
 */
public class LinkedQueue implements Queue {

    static class TreeNode{
        Object val;
        TreeNode next;
    }

    /**
     * 当前长度
     */
    private int size;

    /**
     * 队首元素
     */
    private TreeNode head;

    /**
     * 队尾元素
     */
    private TreeNode tail;

    @Override
    public int size() {
        return this.size;
    }

    @Override
    public boolean isFull() {
        return false;
    }

    @Override
    public Object remove() throws QueueEmptyException {
        if(this.size == 0){
            throw new QueueEmptyException();
        }
        Object element = head.val;
        head = head.next;
        size--;
        return element;
    }

    @Override
    public void insert(Object element) throws QueueFullException {
        TreeNode treeNode = new TreeNode();
        treeNode.val = element;
        //新增第一个元素的特殊处理
        if(size == 0){
            tail = treeNode;
            head = treeNode;
        }else if(size == 1){
        //新增第二个原色的特水处理
            tail.next = treeNode;
            head.next = treeNode;
            tail = treeNode;
        }else{
            tail.next = treeNode;
            tail = treeNode;
        }
        size++;
    }
}

队列的内容比较简单,关于队列,掌握两种实现方式的原理,基本上就足够应对大多数队列相关的算法了。
队列的主要操作只有入队和出队的操作,本篇忘忧实现的为非线程安全的队列,如果对多线程知识有所了解的话,可以尝试着自己实现一下线程安全的队列,在此忘忧就不过多讨论了。

扩展

  • 双向队列

结束语:你不努力,就得出局。

发布了11 篇原创文章 · 获赞 170 · 访问量 11万+

猜你喜欢

转载自blog.csdn.net/u013054715/article/details/104853790