当前位置:   article > 正文

java数据结构系列,第四篇:双端队列_java 双端队列

java 双端队列

双端队列(Double-ended queue,简称Deque)是一种数据结构,允许在队列的两端进行插入和删除操作。它可以被看作是一个允许元素插入和删除的线性表,但与普通队列不同,双端队列支持在队列的头部和尾部进行插入和删除操作,因此具有更加灵活的使用方式。

双端队列的特点包括:

  1. 前端插入和删除: 可以在双端队列的前端执行插入和删除操作。这使得双端队列可以像栈一样用于一些问题,比如实现逆序计算或其他需要后进先出(LIFO)操作的场景。

  2. 后端插入和删除: 同样可以在双端队列的后端执行插入和删除操作。这使得双端队列保持了队列的性质,即先进先出(FIFO)。

双端队列常见的操作包括:

  • 在前端插入元素(push_front):将一个新元素插入到双端队列的头部。
  • 在前端删除元素(pop_front):删除并返回双端队列的头部元素。
  • 在后端插入元素(push_back):将一个新元素插入到双端队列的尾部。
  • 在后端删除元素(pop_back):删除并返回双端队列的尾部元素。
  • 获取前端元素(front):返回双端队列的头部元素,但不进行删除。
  • 获取后端元素(back):返回双端队列的尾部元素,但不进行删除。

双端队列在很多算法和数据结构问题中都有广泛的应用,因为它的灵活性使得它可以同时满足栈和队列的需求。在编程中,许多编程语言提供了标准库中的双端队列实现,以方便开发者使用。

下面分别是用链表和数组实现双端队列:

先定义一个接口:
 

  1. public interface Deque<E>
  2. {
  3. /**
  4. * 从头部插入
  5. * @param e 要插入的元素
  6. * @return 是否插入成功
  7. */
  8. boolean offerFirst(E e);
  9. /**
  10. * 从尾部插入
  11. * @param e 要插入的元素
  12. * @return 是否插入成功
  13. */
  14. boolean offerLast(E e);
  15. /**
  16. * 从头部删除
  17. * @return 被删除的元素
  18. */
  19. E pollFirst();
  20. /**
  21. * 从尾部删除
  22. * @return 被删除的元素
  23. */
  24. E pollLast();
  25. /**
  26. * 从头部查看
  27. * @return 被查看的元素
  28. */
  29. E peekFirst();
  30. /**
  31. * 从尾部查看
  32. * @return 被查看的元素
  33. */
  34. E peekLast();
  35. /**
  36. * 队列是否为空
  37. * @return 是否为空
  38. */
  39. boolean isEmpty();
  40. /**
  41. * 队列是否已满
  42. * @return 是否已满
  43. */
  44. boolean isFull();
  45. }

链表实现:

  1. public class LinkedListDeque<E> implements Deque<E>, Iterable<E>
  2. {
  3. /**
  4. * 双向链表节点类
  5. * @param <E> 节点存储的元素类型
  6. */
  7. static class Node<E>
  8. {
  9. Node<E> prev;//前驱,表示当前节点的前一个节点
  10. E value;//值
  11. Node<E> next;//后继,当前节点的后一个节点
  12. Node(final Node<E> prev,final E value,final Node<E> next)
  13. {
  14. this.prev = prev;
  15. this.value = value;
  16. this.next = next;
  17. }
  18. }
  19. int capacity = Integer.MAX_VALUE;//容量
  20. int size;//当前元素个数
  21. Node<E> sentinel = new Node<>(null,null,null);//哨兵节点
  22. /**
  23. * 构造函数
  24. * @param capacity 容量
  25. */
  26. public LinkedListDeque(final int capacity)
  27. {
  28. this.capacity = capacity;
  29. sentinel.prev = sentinel;
  30. sentinel.next = sentinel;
  31. }
  32. /**
  33. * 构造函数
  34. */
  35. public LinkedListDeque()
  36. {
  37. sentinel.prev = sentinel;
  38. sentinel.next = sentinel;
  39. }
  40. /**
  41. * 迭代器
  42. * @return 迭代器
  43. */
  44. @Override
  45. public Iterator<E> iterator()
  46. {
  47. return new Iterator<E>() {
  48. Node<E> p = sentinel.next;//当前节点
  49. /**
  50. * 是否有下一个元素
  51. * @return 是否有下一个元素,p不等于哨兵节点时有下一个元素
  52. */
  53. @Override
  54. public boolean hasNext()
  55. {
  56. return p != sentinel;
  57. }
  58. /**
  59. * 获取当前元素的值,并将p指向下一个元素
  60. * @return 当前元素的值
  61. */
  62. @Override
  63. public E next()
  64. {
  65. E value = p.value;
  66. p = p.next;
  67. return value;
  68. }
  69. };
  70. }
  71. /**
  72. * 从头部插入
  73. * @param e 要插入的元素
  74. * @return 是否插入成功
  75. */
  76. @Override
  77. public boolean offerFirst(final E e)
  78. {
  79. if (isFull())
  80. {
  81. return false;
  82. }
  83. Node<E> a = sentinel;
  84. Node<E> b = sentinel.next;
  85. Node<E> added = new Node<>(a,e,b);
  86. a.next = added;
  87. b.prev = added;
  88. size ++;
  89. return true;
  90. }
  91. /**
  92. * 从尾部插入
  93. * @param e 要插入的元素
  94. * @return 是否插入成功
  95. */
  96. @Override
  97. public boolean offerLast(final E e)
  98. {
  99. if (isFull())
  100. {
  101. return false;
  102. }
  103. Node<E> a = sentinel.prev;
  104. Node<E> b = sentinel;
  105. Node<E> added = new Node<>(a,e,b);
  106. a.next = added;
  107. b.prev = added;
  108. size ++;
  109. return true;
  110. }
  111. /**
  112. * 从头部删除
  113. * @return 被删除的元素
  114. */
  115. @Override
  116. public E pollFirst()
  117. {
  118. if (isEmpty())
  119. {
  120. return null;
  121. }
  122. Node<E> a = sentinel;
  123. Node<E> removed = sentinel.next;
  124. Node<E> b = removed.next;
  125. a.next = b;
  126. b.prev = a;
  127. size --;
  128. return removed.value;
  129. }
  130. /**
  131. * 从尾部删除
  132. * @return 被删除的元素
  133. */
  134. @Override
  135. public E pollLast()
  136. {
  137. if (isEmpty())
  138. {
  139. return null;
  140. }
  141. Node<E> removed = sentinel.prev;
  142. Node<E> a = removed.prev;
  143. Node<E> b = sentinel;
  144. a.next = b;
  145. b.prev = a;
  146. size --;
  147. return removed.value;
  148. }
  149. /**
  150. * 从头部查看
  151. * @return 被查看的元素
  152. */
  153. @Override
  154. public E peekFirst()
  155. {
  156. if (isEmpty())
  157. {
  158. return null;
  159. }
  160. return sentinel.next.value;
  161. }
  162. /**
  163. * 从尾部查看
  164. * @return 被查看的元素
  165. */
  166. @Override
  167. public E peekLast()
  168. {
  169. if (isEmpty())
  170. {
  171. return null;
  172. }
  173. return sentinel.prev.value;
  174. }
  175. /**
  176. * 队列是否为空
  177. * @return 是否为空
  178. */
  179. @Override
  180. public boolean isEmpty()
  181. {
  182. return size == 0;
  183. }
  184. /**
  185. * 队列是否已满
  186. * @return 是否已满
  187. */
  188. @Override
  189. public boolean isFull()
  190. {
  191. return size == capacity;
  192. }
  193. /**
  194. * 重写toString方法
  195. */
  196. @Override
  197. public String toString()
  198. {
  199. StringBuilder sb = new StringBuilder();
  200. sb.append("[");
  201. int i = 0;
  202. for (E e : this)
  203. {
  204. i ++;
  205. if (i == size)
  206. {
  207. sb.append(e);
  208. }
  209. else
  210. {
  211. sb.append(e);
  212. sb.append(",");
  213. }
  214. }
  215. sb.append("]");
  216. return sb.toString();
  217. }
  218. }

数组实现:
 

  1. public class ArrayDeque1<E> implements Iterable<E>, Deque<E>
  2. {
  3. /**
  4. * 用于给数组下标加1,如果到达数组末尾则返回0
  5. * @param i 当前下标
  6. * @param length 数组长度
  7. * return i+1 下标加1
  8. */
  9. static int inc(int i,int length)
  10. {
  11. if (i + 1 >= length)
  12. {
  13. return 0;
  14. }
  15. return i + 1;
  16. }
  17. /**
  18. * 用于给数组下标减1,如果到达数组头部则返回数组末尾下标
  19. * @param i 当前下标
  20. * @param length 数组长度
  21. * return i-1 下标减1
  22. */
  23. static int dec(int i,int length)
  24. {
  25. if (i - 1 < 0)
  26. {
  27. return length - 1;
  28. }
  29. return i - 1;
  30. }
  31. E[] array;//数组
  32. int head;//头指针,代表该队列的第一个元素
  33. int tail;//尾指针,始终置空,不存储元素,只是用来标记下一次尾部插入时,元素插入的位置
  34. /**
  35. * 构造函数
  36. * @param capacity 容量
  37. */
  38. public ArrayDeque1(int capacity)
  39. {
  40. array = (E[]) new Object[capacity + 1];
  41. }
  42. /**
  43. * 实现迭代器
  44. */
  45. @Override
  46. public Iterator<E> iterator()
  47. {
  48. return new Iterator<E>() {
  49. int p = head;//当前指针
  50. /**
  51. * 是否有下一个元素
  52. * @return 是否有下一个元素,p不等于尾指针时有下一个元素
  53. */
  54. @Override
  55. public boolean hasNext() {
  56. return p != tail;
  57. }
  58. /**
  59. * 获取当前元素的值,并将p指向下一个元素
  60. * @return 当前元素的值
  61. */
  62. @Override
  63. public E next() {
  64. E value = array[p];
  65. p = inc(p,array.length);
  66. return value;
  67. }
  68. };
  69. }
  70. /**
  71. * 从头部插入
  72. * @param e 要插入的元素
  73. * @return 是否插入成功
  74. */
  75. @Override
  76. public boolean offerFirst(E e)
  77. {
  78. if (isFull())
  79. {
  80. return false;
  81. }
  82. head = dec(head,array.length);//头指针向前一步
  83. array[head] = e;//在当前头指针处插入元素
  84. return true;
  85. }
  86. /**
  87. * 从尾部插入
  88. * @param e 要插入的元素
  89. * @return 是否插入成功
  90. */
  91. @Override
  92. public boolean offerLast(E e)
  93. {
  94. if (isFull())
  95. {
  96. return false;
  97. }
  98. array[tail] = e;//在当前尾指针处插入元素
  99. tail = inc(tail,array.length);//尾指针向后一步
  100. return true;
  101. }
  102. /**
  103. * 从头部删除
  104. * @return 被删除的元素
  105. */
  106. @Override
  107. public E pollFirst()
  108. {
  109. if (isEmpty())
  110. {
  111. return null;
  112. }
  113. E e = array[head];
  114. array[head] = null;//清理内存,help GC
  115. head = inc(head,array.length);
  116. return e;
  117. }
  118. @Override
  119. public E pollLast()
  120. {
  121. if (isEmpty())
  122. {
  123. return null;
  124. }
  125. tail = dec(tail,array.length);
  126. E e = array[tail];
  127. array[tail] = null;//help GC
  128. return e;
  129. }
  130. /**
  131. * 从头部查看
  132. * @return 被查看的元素
  133. */
  134. @Override
  135. public E peekFirst()
  136. {
  137. if (isEmpty())
  138. {
  139. return null;
  140. }
  141. return array[head];
  142. }
  143. /**
  144. * 从尾部查看
  145. * @return 被查看的元素
  146. */
  147. @Override
  148. public E peekLast()
  149. {
  150. if (isEmpty())
  151. {
  152. return null;
  153. }
  154. return array[dec(tail,array.length)];
  155. }
  156. /**
  157. * 队列是否为空
  158. * @return 是否为空
  159. */
  160. @Override
  161. public boolean isEmpty()
  162. {
  163. return head == tail;
  164. }
  165. /**
  166. * 队列是否已满,两种情况:
  167. * 1.如果尾指针在头指针后面,则当尾指针减头指针等于数组长度减1时,队列已满
  168. * 2.如果尾指针在头指针前面,则当头指针减尾指针等于1时,也就是头指针紧挨着尾指针,队列已满
  169. * @return 是否已满
  170. */
  171. @Override
  172. public boolean isFull()
  173. {
  174. if (tail > head)
  175. {
  176. return tail - head == array.length - 1;
  177. }
  178. else if (tail < head)
  179. {
  180. return head - tail == 1;
  181. }
  182. else
  183. {
  184. return false;
  185. }
  186. }
  187. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/78797
推荐阅读
相关标签
  

闽ICP备14008679号