1、线性表之队列(queue)

  1. 1、队列(Queue)-概述:
  2. 1-1、队列是只允许在一端进行插入,在另一端进行删除操作的线性表。允许插入的一端成为队尾,允许删除的一端称为队头。
  3. 1-2、队列是先进先出(FIFO-First in, First out)的线性表。
  4. 2、队列(Queue)-使用场景:
  5. 2-1、因为队列先进先出的特点,在多线程阻塞队列管理中非常适用。

1.1、队列(Queue)-存储结构/分类

  1. 1、队列(Queue)-存储结构/分类:
  2. 1-1、顺序存储结构:使用数组实现的叫静态队列
  3. 1-1-1、插入元素的时间复杂度为O(1),删除元素事前面的元素删除之后,后面的元素都要向前挪,因此其时间复杂度为O(N)。
  4. 1-2、链式存储结构:使用链表实现的叫动态队列
  5. 1-2-1、插入元素的时间复杂度为O(1),引入front [frʌnt]和rear [rɪə(r)]指针,front指向队头,rear指向队尾,当两者相等时,front=rear说明队列满,但是front=rear也说明队列为空。。因此删除操作其时间复杂度为O(N)。

1.1.1、线性表之队列(queue)-顺序存储结构及实现-Demo

  1. 1、顺序存储结构及实现-Demo
  2. public class SequenceQueue<T> {
  3. private int DEFAULT_SIZE = 10;
  4. //保存数组的长度。
  5. private int capacity;
  6. //定义一个数组用于保存顺序队列的元素
  7. private Object[] elementData;
  8. //保存顺序队列中元素的当前个数
  9. private int front = 0;
  10. private int rear = 0;
  11. //以默认数组长度创建空顺序队列
  12. public SequenceQueue() {
  13. capacity = DEFAULT_SIZE;
  14. elementData = new Object[capacity];
  15. }
  16. //以一个初始化元素来创建顺序队列
  17. public SequenceQueue(T element) {
  18. this();
  19. elementData[0] = element;
  20. rear++;
  21. }
  22. /**
  23. * 以指定长度的数组来创建顺序队列
  24. * @param element 指定顺序队列中第一个元素
  25. * @param initSize 指定顺序队列底层数组的长度
  26. */
  27. public SequenceQueue(T element , int initSize) {
  28. this.capacity = initSize;
  29. elementData = new Object[capacity];
  30. elementData[0] = element;
  31. rear++;
  32. }
  33. //获取顺序队列的大小
  34. public int length() {
  35. return rear - front;
  36. }
  37. //插入队列
  38. public void add(T element) {
  39. if (rear > capacity - 1) {
  40. throw new IndexOutOfBoundsException("队列已满的异常");
  41. }
  42. elementData[rear++] = element;
  43. }
  44. //移除队列
  45. public T remove() {
  46. if (empty()) {
  47. throw new IndexOutOfBoundsException("空队列异常");
  48. }
  49. //保留队列的rear端的元素的值
  50. T oldValue = (T)elementData[front];
  51. //释放队列的rear端的元素
  52. elementData[front++] = null;
  53. return oldValue;
  54. }
  55. //返回队列顶元素,但不删除队列顶元素
  56. public T element() {
  57. if (empty()) {
  58. throw new IndexOutOfBoundsException("空队列异常");
  59. }
  60. return (T)elementData[front];
  61. }
  62. //判断顺序队列是否为空队列
  63. public boolean empty() {
  64. return rear == front;
  65. }
  66. //清空顺序队列
  67. public void clear() {
  68. //将底层数组所有元素赋为null
  69. Arrays.fill(elementData , null);
  70. front = 0;
  71. rear = 0;
  72. }
  73. public String toString() {
  74. if (empty()) {
  75. return "[]";
  76. }else{
  77. StringBuilder sb = new StringBuilder("[");
  78. for (int i = front ; i < rear ; i++ ) {
  79. sb.append(elementData[i].toString() + ", ");
  80. }
  81. int len = sb.length();
  82. return sb.delete(len - 2 , len).append("]").toString();
  83. }
  84. }
  85. }

1.1.2、线性表之队列(queue)-循环存储结构及实现-Demo

  1. 1、循环存储结构及实现-Demo
  2. public class LoopQueue<T> {
  3. private int DEFAULT_SIZE = 10;
  4. //保存数组的长度。
  5. private int capacity;
  6. //定义一个数组用于保存循环队列的元素
  7. private Object[] elementData;
  8. //保存循环队列中元素的当前个数
  9. private int front = 0;
  10. private int rear = 0;
  11. //以默认数组长度创建空循环队列
  12. public LoopQueue() {
  13. capacity = DEFAULT_SIZE;
  14. elementData = new Object[capacity];
  15. }
  16. //以一个初始化元素来创建循环队列
  17. public LoopQueue(T element) {
  18. this();
  19. elementData[0] = element;
  20. rear++;
  21. }
  22. /**
  23. * 以指定长度的数组来创建循环队列
  24. * @param element 指定循环队列中第一个元素
  25. * @param initSize 指定循环队列底层数组的长度
  26. */
  27. public LoopQueue(T element , int initSize) {
  28. this.capacity = initSize;
  29. elementData = new Object[capacity];
  30. elementData[0] = element;
  31. rear++;
  32. }
  33. //获取循环队列的大小
  34. public int length() {
  35. if (empty())
  36. {
  37. return 0;
  38. }
  39. return rear > front ? rear - front
  40. : capacity - (front - rear);
  41. }
  42. //插入队列
  43. public void add(T element) {
  44. if (rear == front && elementData[front] != null) {
  45. throw new IndexOutOfBoundsException("队列已满的异常");
  46. }
  47. elementData[rear++] = element;
  48. //如果rear已经到头,那就转头
  49. rear = rear == capacity ? 0 : rear;
  50. }
  51. //移除队列
  52. public T remove() {
  53. if (empty()) {
  54. throw new IndexOutOfBoundsException("空队列异常");
  55. }
  56. //保留队列的rear端的元素的值
  57. T oldValue = (T)elementData[front];
  58. //释放队列的rear端的元素
  59. elementData[front++] = null;
  60. //如果front已经到头,那就转头
  61. front = front == capacity ? 0 : front;
  62. return oldValue;
  63. }
  64. //返回队列顶元素,但不删除队列顶元素
  65. public T element() {
  66. if (empty()) {
  67. throw new IndexOutOfBoundsException("空队列异常");
  68. }
  69. return (T)elementData[front];
  70. }
  71. //判断循环队列是否为空队列
  72. public boolean empty(){
  73. //rear==front且rear处的元素为null
  74. return rear == front && elementData[rear] == null;
  75. }
  76. //清空循环队列
  77. public void clear() {
  78. //将底层数组所有元素赋为null
  79. Arrays.fill(elementData , null);
  80. front = 0;
  81. rear = 0;
  82. }
  83. public String toString() {
  84. if (empty()) {
  85. return "[]";
  86. }else{
  87. //如果front < rear,有效元素就是front到rear之间的元素
  88. if (front < rear){
  89. StringBuilder sb = new StringBuilder("[");
  90. for (int i = front ; i < rear ; i++ ){
  91. sb.append(elementData[i].toString() + ", ");
  92. }
  93. int len = sb.length();
  94. return sb.delete(len - 2 , len).append("]").toString();
  95. }
  96. //如果front >= rear,有效元素为front->capacity之间、0->front之间的
  97. else{
  98. StringBuilder sb = new StringBuilder("[");
  99. for (int i = front ; i < capacity ; i++ ) {
  100. sb.append(elementData[i].toString() + ", ");
  101. }
  102. for (int i = 0 ; i < rear ; i++){
  103. sb.append(elementData[i].toString() + ", ");
  104. }
  105. int len = sb.length();
  106. return sb.delete(len - 2 , len).append("]").toString();
  107. }
  108. }
  109. }
  110. }

1.1.2、线性表之队列(queue)-链式存储结构及实现-Demo

  1. 1、链式存储结构及实现-Demo
  2. public class LinkQueue<T> {
  3. //保存该链队列的头节点
  4. private Node front;
  5. //保存该链队列的尾节点
  6. private Node rear;
  7. //保存该链队列中已包含的节点数
  8. private int size;
  9. //定义一个内部类Node,Node实例代表链队列的节点。
  10. private class Node {
  11. //保存节点的数据
  12. private T data;
  13. //指向下个节点的引用
  14. private Node next;
  15. //无参数的构造器
  16. public Node() {}
  17. //初始化全部属性的构造器
  18. public Node(T data , Node next){
  19. this.data = data;
  20. this.next = next;
  21. }
  22. }
  23. //创建空链队列
  24. public LinkQueue() {
  25. //空链队列,front和rear都是null
  26. front = null;
  27. rear = null;
  28. }
  29. //以指定数据元素来创建链队列,该链队列只有一个元素
  30. public LinkQueue(T element) {
  31. front = new Node(element , null);
  32. //只有一个节点,front、rear都指向该节点
  33. rear = front;
  34. size++;
  35. }
  36. //返回链队列的长度
  37. public int length(){
  38. return size;
  39. }
  40. //将新元素加入队列
  41. public void add(T element) {
  42. //如果该链队列还是空链队列
  43. if (front == null) {
  44. front = new Node(element , null);
  45. //只有一个节点,front、rear都指向该节点
  46. rear = front;
  47. }else{
  48. //创建新节点
  49. Node newNode = new Node(element , null);
  50. //让尾节点的next指向新增的节点
  51. rear.next = newNode;
  52. //以新节点作为新的尾节点
  53. rear = newNode;
  54. }
  55. size++;
  56. }
  57. //删除队列front端的元素
  58. public T remove() {
  59. Node oldFront = front;
  60. front = front.next;
  61. oldFront.next = null;
  62. size--;
  63. return oldFront.data;
  64. }
  65. //访问链式队列中最后一个元素
  66. public T element() {
  67. return rear.data;
  68. }
  69. //判断链式队列是否为空队列
  70. public boolean empty() {
  71. return size == 0;
  72. }
  73. //清空链队列
  74. public void clear() {
  75. //将front、rear两个节点赋为null
  76. front = null;
  77. rear = null;
  78. size = 0;
  79. }
  80. public String toString() {
  81. //链队列为空链队列时
  82. if (empty()) {
  83. return "[]";
  84. }else{
  85. StringBuilder sb = new StringBuilder("[");
  86. for (Node current = front ; current != null ; current = current.next ){
  87. sb.append(current.data.toString() + ", ");
  88. }
  89. int len = sb.length();
  90. return sb.delete(len - 2 , len).append("]").toString();
  91. }
  92. }
  93. }