先进先出队列(简称队列)是一种基于先进先出(FIFO)策略的集合类型。可以使用数组链表实现。

API

成员函数(Item 是泛型变量) 功能
Queue() 创建空队列
void enqueue() 添加一个元素
Item dequeue() 删除最早添加的元素
boolean isEmpty() 队列是否为空
int size() 队列中的元素数量

实现

两种实现都支持 forEach 迭代。

数组实现

  1. import java.util.Iterator;
  2. import java.util.NoSuchElementException;
  3. import java.util.Random;
  4. public class ResizingArrayQueue<Item> implements Iterable<Item> {
  5. // 初始化队列数组大小
  6. private static final int INIT_CAPACITY = 8;
  7. // 队列元素数组
  8. private Item[] q;
  9. // 当前队列的元素数量
  10. private int n;
  11. // 队列头部元素
  12. private int first;
  13. // 队列尾部元素
  14. private int last;
  15. /**
  16. * 初始化空队列
  17. */
  18. public ResizingArrayQueue() {
  19. q = (Item[]) new Object[INIT_CAPACITY];
  20. n = 0;
  21. first = 0;
  22. last = 0;
  23. }
  24. /**
  25. * 当前队列是否为空
  26. *
  27. * @return 为空返回 true,否则放回 false
  28. */
  29. public boolean isEmpty() {
  30. return n == 0;
  31. }
  32. /**
  33. * 当前队列的元素数量
  34. *
  35. * @return 元素数量
  36. */
  37. public int size() {
  38. return n;
  39. }
  40. /**
  41. * 动态调整队列数组大小
  42. *
  43. * @param capacity
  44. */
  45. private void resize(int capacity) {
  46. assert capacity >= n;
  47. Item[] copy = (Item[]) new Object[capacity];
  48. for (int i = 0; i < n; i++) {
  49. copy[i] = q[(first + i) % q.length];
  50. }
  51. q = copy;
  52. first = 0;
  53. last = n;
  54. }
  55. /**
  56. * 添加一个元素
  57. *
  58. * @param item
  59. */
  60. public void enqueue(Item item) {
  61. if (n == q.length) resize(2 * q.length);
  62. q[last++] = item;
  63. if (last == q.length) last = 0;
  64. n++;
  65. }
  66. /**
  67. * 删除队列最早添加的元素
  68. *
  69. * @return 队列最早添加的元素
  70. */
  71. public Item dequeue() {
  72. if (isEmpty()) throw new NoSuchElementException("Queue underflow");
  73. Item item = q[first];
  74. q[first] = null;
  75. n--;
  76. first++;
  77. if (first == q.length) first = 0;
  78. if (n > 0 && n == q.length / 4) resize(q.length / 2);
  79. return item;
  80. }
  81. /**
  82. * 查看队列最早添加元素(不删除)
  83. *
  84. * @return 队列最早添加的元素
  85. */
  86. public Item peek() {
  87. if (isEmpty()) throw new NoSuchElementException("Queue underflow");
  88. return q[first];
  89. }
  90. /**
  91. * forEach 迭代
  92. *
  93. * @return
  94. */
  95. public Iterator<Item> iterator() {
  96. return new ArrayIterator();
  97. }
  98. private class ArrayIterator implements Iterator<Item> {
  99. private int i = 0;
  100. public boolean hasNext() {
  101. return i < n;
  102. }
  103. public void remove() {
  104. throw new UnsupportedOperationException();
  105. }
  106. public Item next() {
  107. if (!hasNext()) throw new NoSuchElementException();
  108. Item item = q[(i + first) % q.length];
  109. i++;
  110. return item;
  111. }
  112. }
  113. public static void main(String[] args) {
  114. ResizingArrayQueue<String> queue = new ResizingArrayQueue<>();
  115. for (int i = 0; i < 8; i++) {
  116. // generator random string
  117. int leftLimit = 97; // letter 'a'
  118. int rightLimit = 122; // letter 'z'
  119. int targetStringLength = 3;
  120. Random random = new Random();
  121. String generatedString = random.ints(leftLimit, rightLimit + 1)
  122. .limit(targetStringLength)
  123. .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
  124. .toString();
  125. queue.enqueue(generatedString);
  126. }
  127. System.out.println("isEmpty: " + queue.isEmpty());
  128. System.out.println("size: " + queue.size());
  129. System.out.println("peek: " + queue.peek());
  130. System.out.println();
  131. for (String s : queue) {
  132. System.out.println("str: " + s);
  133. }
  134. }
  135. }

其中在 resize() 和 next() 方法中有这么一句代码:

  1. Item item = q[(i + first) % q.length];

还有 enqueue() 和 dequeue() 中的代码:

  1. if (last == q.length) last = 0; // enqueue()
  2. if (first == q.length) first = 0; // dequeue()

对应的是这种情况:

ResizingArrayStack.jpg

链表实现

  1. package chapter1.c1_3;
  2. import java.util.Iterator;
  3. import java.util.NoSuchElementException;
  4. import java.util.Random;
  5. public class LinkedQueue<Item> implements Iterable<Item> {
  6. private int n;
  7. private Node first;
  8. private Node last;
  9. /**
  10. * 内部结点类
  11. */
  12. private class Node {
  13. private Item item;
  14. private Node next;
  15. }
  16. /**
  17. * 初始化空栈
  18. */
  19. private LinkedQueue() {
  20. first = null;
  21. last = null;
  22. n = 0;
  23. assert check();
  24. }
  25. /**
  26. * 是否为空栈
  27. *
  28. * @return 为空返回 true,否则返回 false
  29. */
  30. public boolean isEmpty() {
  31. return first == null;
  32. }
  33. public int size() {
  34. return n;
  35. }
  36. /**
  37. * 查看最早添加的元素(不删除)
  38. *
  39. * @return 最早添加的元素
  40. */
  41. public Item peek() {
  42. if (isEmpty()) throw new NoSuchElementException("Queue underflow");
  43. return first.item;
  44. }
  45. /**
  46. * 添加一个元素
  47. *
  48. * @param item
  49. */
  50. public void enqueue(Item item) {
  51. Node oldLast = last;
  52. last = new Node();
  53. last.item = item;
  54. last.next = null;
  55. if (isEmpty()) first = last;
  56. else oldLast.next = last;
  57. n++;
  58. assert check();
  59. }
  60. /**
  61. * 删除最早添加的元素
  62. *
  63. * @return 最早添加的元素
  64. */
  65. public Item dequeue() {
  66. if (isEmpty()) throw new NoSuchElementException("Queue underflow");
  67. Item item = first.item;
  68. first = first.next;
  69. n--;
  70. if (isEmpty()) last = null;
  71. assert check();
  72. return item;
  73. }
  74. /**
  75. * 元素转化为字符串
  76. *
  77. * @return 字符串
  78. */
  79. public String toString() {
  80. StringBuilder s = new StringBuilder();
  81. for (Item item : this) {
  82. s.append(item).append(" ");
  83. }
  84. return s.toString();
  85. }
  86. /**
  87. * 检测内部变量
  88. *
  89. * @return 全部通过返回 true,否则返回 false
  90. */
  91. public boolean check() {
  92. if (n < 0) {
  93. return false;
  94. } else if (n == 0) {
  95. if (first != null) return false;
  96. return last == null;
  97. } else if (n == 1) {
  98. if (first == null || last == null) return false;
  99. if (first != last) return false;
  100. return first.next == null;
  101. } else {
  102. if (first == null || last == null) return false;
  103. if (first == last) return false;
  104. if (first.next == null) return false;
  105. if (last.next != null) return false;
  106. int numberOfNodes = 0;
  107. for (Node x = first; x != null && numberOfNodes <= n; x = x.next) {
  108. numberOfNodes++;
  109. }
  110. if (numberOfNodes != n) return false;
  111. Node lastNode = first;
  112. while (lastNode.next != null) {
  113. lastNode = lastNode.next;
  114. }
  115. return last == lastNode;
  116. }
  117. }
  118. /**
  119. * 支持 forEach 迭代
  120. *
  121. * @return
  122. */
  123. @Override
  124. public Iterator<Item> iterator() {
  125. return new LinkedIterator();
  126. }
  127. private class LinkedIterator implements Iterator<Item> {
  128. private Node current = first;
  129. @Override
  130. public boolean hasNext() {
  131. return current != null;
  132. }
  133. @Override
  134. public Item next() {
  135. if (!hasNext()) throw new NoSuchElementException();
  136. Item item = current.item;
  137. current = current.next;
  138. return item;
  139. }
  140. @Override
  141. public void remove() {
  142. throw new UnsupportedOperationException();
  143. }
  144. }
  145. public static void main(String[] args) {
  146. ResizingArrayQueue<String> queue = new ResizingArrayQueue<>();
  147. for (int i = 0; i < 8; i++) {
  148. // generator random string
  149. int leftLimit = 97; // letter 'a'
  150. int rightLimit = 122; // letter 'z'
  151. int targetStringLength = 3;
  152. Random random = new Random();
  153. String generatedString = random.ints(leftLimit, rightLimit + 1)
  154. .limit(targetStringLength)
  155. .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
  156. .toString();
  157. queue.enqueue(generatedString);
  158. }
  159. System.out.println("isEmpty: " + queue.isEmpty());
  160. System.out.println("size: " + queue.size());
  161. System.out.println("peek: " + queue.peek());
  162. System.out.println();
  163. for (String s : queue) {
  164. System.out.println("str: " + s);
  165. }
  166. }
  167. }

对应的图:

linkedQueue.jpg

附件:

LinkedQueue.drawioResizingArrayStack.drawio

参考: