使用JAVA实现队列的数据结构

队列,是一种特殊的链表,是一种只能在表尾进行插入,表头进行删除的特殊链表,是一种先进先出的结构。

一、队列的结构

队列本质是一种链表,因此栈存储结构与链表一致,形象图如下:

整个栈像我们日常生活中的排队,每个排队的人物就是一个队列元素,新来的人只能排在队尾,从开始依次出队

1.给队列添加元素

给队列添加元素

  • 就像在食堂打饭,后来的人就得在队列后面排着,前面的人先到打饭窗口打饭
2.从队列里面删除元素

从队列中删除元素

  • 在食堂打饭,队列的第一个人,排在打饭窗口,他打完饭,就离开这个队列了

二、通过数组实现栈

通过数组来实现栈是比较简单的,因为栈只操作表尾,即数组的最后一个元素,其主要操作主要是入栈和出栈。

1.入列

在队尾添加节点

2.出列

弹出队首元素节点

3.通过数组来实现队列这种数据结构
  1. package com.shixinke.demo.dataStruct;
  2. public class MyArrayQueue<E> {
  3. /**
  4. * 队列长度
  5. */
  6. private int size;
  7. /**
  8. * 队列数据
  9. */
  10. private E[] data;
  11. /**
  12. * 默认队列长度
  13. */
  14. private static final int DEFAULT_CAPACITY = 10;
  15. public MyArrayQueue() {
  16. clearQueue(DEFAULT_CAPACITY);
  17. }
  18. public MyArrayQueue(int capacity) {
  19. clearQueue(capacity);
  20. }
  21. public void clear() {
  22. clearQueue(DEFAULT_CAPACITY);
  23. }
  24. public int size() {
  25. return this.size;
  26. }
  27. public boolean isEmpty() {
  28. return this.size == 0;
  29. }
  30. /**
  31. * 入列
  32. * @param element
  33. * @return
  34. */
  35. public boolean push(E element) {
  36. if (size == data.length) {
  37. ensureCapacity(size * 2 +1);
  38. }
  39. data[size] = element;
  40. size ++;
  41. return true;
  42. }
  43. /**
  44. * 出列
  45. * @return
  46. */
  47. public E shift() {
  48. if (size == 0) {
  49. return null;
  50. }
  51. E node = data[0];
  52. for (int i = 0; i< size - 1; i++) {
  53. data[i] = data[i+1];
  54. }
  55. data[size -1] = null;
  56. this.size --;
  57. return node;
  58. }
  59. public boolean contains(E element) {
  60. return indexOf(element) >= 0 ? true : false;
  61. }
  62. public int indexOf(E element) {
  63. if (element == null) {
  64. for (int i = 0; i< this.size; i++) {
  65. if (data[i] == null) {
  66. return i;
  67. }
  68. }
  69. } else {
  70. for (int i = 0; i< this.size; i++) {
  71. if (element.equals(data[i])) {
  72. return i;
  73. }
  74. }
  75. }
  76. return -1;
  77. }
  78. public int lastIndexOf(E element) {
  79. if (element == null) {
  80. for (int i = this.size -1; i >= 0; i -- ) {
  81. if (data[i] == null) {
  82. return i;
  83. }
  84. }
  85. } else {
  86. for (int i = this.size -1; i >= 0; i -- ) {
  87. if (element.equals(data[i])) {
  88. return i;
  89. }
  90. }
  91. }
  92. return -1;
  93. }
  94. public void print() {
  95. System.out.println();
  96. System.out.print("[");
  97. for (int i = 0; i< this.size; i++) {
  98. System.out.print(data[i]);
  99. if (i != this.size - 1) {
  100. System.out.print(",");
  101. }
  102. }
  103. System.out.println("]");
  104. System.out.println();
  105. }
  106. public static void main(String[] args) {
  107. MyArrayQueue<String> books = new MyArrayQueue<String>(5);
  108. books.push("JAVA编程");
  109. books.push("网络安全");
  110. books.push("计算机网络");
  111. books.push("计算机文化基础");
  112. books.print(); //[JAVA编程,网络安全,计算机网络,计算机文化基础]
  113. String lastBook = books.shift();
  114. System.out.println(lastBook); //JAVA编程
  115. books.print(); //[网络安全,计算机网络,计算机文化基础]
  116. System.out.println(books.size()); //3
  117. System.out.println(books.contains("计算机网络")); //true
  118. System.out.println(books.indexOf("计算机网络")); //1
  119. }
  120. private void clearQueue(int capacity) {
  121. this.size = 0;
  122. ensureCapacity(capacity);
  123. }
  124. private void ensureCapacity(int capacity) {
  125. if (capacity < this.size) {
  126. return;
  127. }
  128. E[] oldData = data;
  129. data = (E[]) new Object[capacity];
  130. for (int i = 0; i < this.size; i++) {
  131. data[i] = oldData[i];
  132. }
  133. }
  134. }

三、通过链表实现队列

1.入列

通过链表实现入列

  • 生成一个新的节点(它的prev指针指向表尾节点,next指针指向null)
  • 将原表尾节点的next指针指向新表尾节点
  • 将新表尾指向新的表尾节点
  • 表节点个数加1
2.出列

通过链表实现出列

  • 将原表头节点的下一个节点的prev指向指向null
  • 将表头指向原节点的下一个节点
  • 清除了原表头的资源,内容和next指针都为null
  • 表节点个数减1
3.通过链表实现栈
  1. package com.shixinke.demo.dataStruct;
  2. public class MyLinkedQueue<E> {
  3. /**
  4. * 队列长度
  5. */
  6. private int size;
  7. /**
  8. * 队头
  9. */
  10. private Node<E> head;
  11. /**
  12. * 队尾
  13. */
  14. private Node<E> tail;
  15. public MyLinkedQueue() {
  16. clearQueue();
  17. }
  18. public void clear() {
  19. clearQueue();
  20. }
  21. private void clearQueue() {
  22. head = null;
  23. tail = null;
  24. size = 0;
  25. }
  26. public int size() {
  27. return size;
  28. }
  29. public boolean isEmpty() {
  30. return size == 0 ;
  31. }
  32. /**
  33. * 入列
  34. * @param element
  35. * @return
  36. */
  37. public boolean push(E element) {
  38. //1.生成新元素节点,它的上一个元素为原表尾
  39. Node<E> newNode = new Node(element, tail, null);
  40. //2.如果表头是空,那么新元素就是表头
  41. if (head == null) {
  42. head = newNode;
  43. }
  44. //4.如果原队列不为空,那么原表尾的下个元素为新节点
  45. tail.next = newNode;
  46. //5.新表必为新节点
  47. tail = newNode;
  48. //6.增加队列的个数
  49. size ++;
  50. return true;
  51. }
  52. /**
  53. * 入列
  54. * @return
  55. */
  56. public E shift() {
  57. //1.如果表头为null,即是空队列,立即返回
  58. if (head == null) {
  59. return null;
  60. }
  61. //2.获取原表头的元素
  62. E item = head.item;
  63. //3.获取原表头的下一个元素
  64. Node<E> newHead = head.next;
  65. if (newHead != null) {
  66. //如果存在下一个元素,将下一个元素的prev指向null
  67. head.next.prev = null;
  68. }
  69. //4.清除原表头的资源
  70. head.next = null;
  71. head.item = null;
  72. //5.设置新表头
  73. head = newHead;
  74. //6.队列元素个数减1
  75. size --;
  76. return item;
  77. }
  78. public boolean contains(E element) {
  79. return indexOf(element) >= 0;
  80. }
  81. public int indexOf(E element) {
  82. if (head == null) {
  83. return -1;
  84. }
  85. Node<E> p = head;
  86. if (element == null) {
  87. for (int i = 0; i< size; i++) {
  88. if (p.item == null) {
  89. return i;
  90. }
  91. p = p.next;
  92. }
  93. } else {
  94. for (int i = 0; i< size; i++) {
  95. if (element.equals(p.item)) {
  96. return i;
  97. }
  98. p = p.next;
  99. }
  100. }
  101. return -1;
  102. }
  103. public int lastIndexOf(E element) {
  104. if (tail == null) {
  105. return -1;
  106. }
  107. Node<E> p = tail;
  108. if (element == null) {
  109. for (int i = size -1; i >= 0; i--) {
  110. if (p.item == null) {
  111. return i;
  112. }
  113. p = p.next;
  114. }
  115. } else {
  116. for (int i = size -1; i >= 0; i--) {
  117. if (element.equals(p.item)) {
  118. return i;
  119. }
  120. p = p.next;
  121. }
  122. }
  123. return -1;
  124. }
  125. public void print() {
  126. System.out.println();
  127. Node<E> node = head;
  128. System.out.print("[");
  129. for (int i = 0; i< this.size; i++) {
  130. System.out.print(node.item);
  131. node = node.next;
  132. if (node != null) {
  133. System.out.print(",");
  134. }
  135. }
  136. System.out.print("]");
  137. System.out.println();
  138. }
  139. public static void main(String[] args) {
  140. MyLinkedQueue<String> books = new MyLinkedQueue<String>();
  141. books.push("JAVA编程");
  142. books.push("网络安全");
  143. books.push("计算机网络");
  144. books.push("计算机文化基础");
  145. books.print(); //[JAVA编程,网络安全,计算机网络,计算机文化基础]
  146. String lastBook = books.shift();
  147. System.out.println(lastBook); //JAVA编程
  148. books.print(); //[网络安全,计算机网络,计算机文化基础]
  149. System.out.println(books.size()); //3
  150. System.out.println(books.contains("计算机网络")); //true
  151. System.out.println(books.indexOf("计算机网络")); //1
  152. }
  153. /**
  154. * 队列节点
  155. * @param <E>
  156. */
  157. private class Node<E> {
  158. /**
  159. * 前节点
  160. */
  161. private Node<E> prev;
  162. /**
  163. * 后节点
  164. */
  165. private Node<E> next;
  166. /**
  167. * 节点元素
  168. */
  169. private E item;
  170. public Node(E item, Node<E> prev, Node<E> next) {
  171. this.item = item;
  172. this.prev = prev;
  173. this.next = next;
  174. }
  175. }
  176. }