美文网首页
数据结构与算法(五)队列

数据结构与算法(五)队列

作者: 0胡杨0 | 来源:发表于2020-03-25 12:33 被阅读0次

    队列的理解

    队列是一种受限的线性表数据结构,它的主要特点就是先进先出.队列的基本操作有两个,入队(enqueue)和出队(dequeue).
    实现一个队列需要两个指针,一个head指向队头,一个tail指向队尾.


    当出队和入队的时候head指针持续的向后移动.
    当tail移动到最右边,即使队列中还有还有空闲的空间也无法向其中添加数据了,这个时候就需要进行数据搬移.

    队列的实现方式

    队列可以用数组实现,叫做顺序队列.也可以用链表实现,叫做链式队列.

    顺序队列的实现代码
    // 用数组实现的队列
    public class ArrayQueue {
      // 数组:items,数组大小:n
      private String[] items;
      private int n = 0;
      // head表示队头下标,tail表示队尾下标
      private int head = 0;
      private int tail = 0;
    
      // 申请一个大小为capacity的数组
      public ArrayQueue(int capacity) {
        items = new String[capacity];
        n = capacity;
      }
    
    // 入队操作,将item放入队尾
      public boolean enqueue(String item) {
        // tail == n表示队列末尾没有空间了
        if (tail == n) {
          // tail ==n && head==0,表示整个队列都占满了
          if (head == 0) return false;
          // 数据搬移
          for (int i = head; i < tail; ++i) {
            items[i-head] = items[i];
          }
          // 搬移完之后重新更新head和tail
          tail -= head;
          head = 0;
        }
        
        items[tail] = item;
        ++tail;
        return true;
      }
    
      // 出队
      public String dequeue() {
        // 如果head == tail 表示队列为空
        if (head == tail) return null;
        // 为了让其他语言的同学看的更加明确,把--操作放到单独一行来写了
        String ret = items[head];
        ++head;
        return ret;
      }
    }
    

    循环队列

    循环队列就像一个环一样,把本来的一条直线变为了首尾相连,
    我们可以看到,图中这个队列的大小为 8,当前 head=4,tail=7。当有一个新的元素 a 入队时,我们放入下标为 7 的位置。但这个时候,我们并不把 tail 更新为 8,而是将其在环中后移一位,到下标为 0 的位置。当再有一个元素 b 入队时,我们将 b 放入下标为 0 的位置,然后 tail 加 1 更新为 1。所以,在 a,b 依次入队之后,循环队列中的元素就变成了下面的样子:

    队满的判断条件

    (tail+1)%n = head


    又上图可以看出循环队列队满的时候tail位置也是没有数据的,说明循环队列会浪费一个存储空间.

    循环队列的实现

    public class CircularQueue {
      // 数组:items,数组大小:n
      private String[] items;
      private int n = 0;
      // head表示队头下标,tail表示队尾下标
      private int head = 0;
      private int tail = 0;
      // 申请一个大小为capacity的数组
      public CircularQueue(int capacity) {
        items = new String[capacity];
        n = capacity;
      }
      // 入队
      public boolean enqueue(String item) {
        // 队列满了
        if ((tail + 1) % n == head) return false;
        items[tail] = item;
        tail = (tail + 1) % n;
        return true;
      }
      // 出队
      public String dequeue() {
        // 如果head == tail 表示队列为空
        if (head == tail) return null;
        String ret = items[head];
        head = (head + 1) % n;
        return ret;
      }
    }
    

    阻塞队列

    其实就是在队列基础上增加了阻塞操作。简单来说,就是在队列为空的时候,从队头取数据会被阻塞。因为此时还没有数据可取,直到队列中有了数据才能返回;如果队列已经满了,那么插入数据的操作就会被阻塞,直到队列中有空闲位置后再插入数据,然后再返回。

    并发队列

    并发队列就是队列的操作多线程安全。
    练习:队列
    ps:内容整理自极客时间--数据结构与算法之美

    相关文章

      网友评论

          本文标题:数据结构与算法(五)队列

          本文链接:https://www.haomeiwen.com/subject/mnvayhtx.html