数据结构与算法-队列
什么是队列
跟栈一样是一种操作受限的线性数据结构,满足先进先出的特性
顺序队列实现例子
1 // 用数组实现的队列 2 public class ArrayQueue { 3 // 数组:items,数组大小:n 4 private String[] items; 5 private int n = 0; 6 // head表示队头下标,tail表示队尾下标 7 private int head = 0; 8 private int tail = 0; 9 10 // 申请一个大小为capacity的数组 11 public ArrayQueue(int capacity) { 12 items = new String[capacity]; 13 n = capacity; 14 } 15 16 // 入队 17 public boolean enqueue(String item) { 18 // 如果tail == n 表示队列已经满了 19 if (tail == n) return false; 20 items[tail] = item; 21 ++tail; 22 return true; 23 } 24 25 // 出队 26 public String dequeue() { 27 // 如果head == tail 表示队列为空 28 if (head == tail) return null; 29 // 为了让其他语言的同学看的更加明确,把--操作放到单独一行来写了 30 String ret = items[head]; 31 ++head; 32 return ret; 33 } 34 }
基于链表的队列实现例子
需要两个指针:head 指针和 tail 指针。它们分别指向链表的第一个结点和最后一个结点。如图所示,入队时,tail->next= new_node, tail = tail->next;出队时,head = head->next
循环队列
用数组来实现队列的时候,在 tail==n 时,会有数据搬移操作,这样入队操作性能就会受到影响。那有没有办法能够避免数据搬移呢?我们来看看循环队列的解决思路。
这个队列的大小为 8,当前 head=4,tail=7。当有一个新的元素 a 入队时,我们放入下标为 7 的位置。但这个时候,我们并不把 tail 更新为 8,而是将其在环中后移一位,到下标为 0 的位置。当再有一个元素 b 入队时,我们将 b 放入下标为 0 的位置,然后 tail 加 1 更新为 1。所以,在 a,b 依次入队之后,循环队列中的元素就变成了下面的样子:
当队列满了 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; } }