经典数据结构和算法 双端队列 java

举报
风吹稻花香 发表于 2021/06/04 22:41:35 2021/06/04
【摘要】 选一个简单的数据结构聊一聊,话说有很多数据结构都在玩组合拳,比如说:块状链表,块状数组,当然还有本篇的双端队列,是的,它就是 栈和队列的组合体。 一:概念      我们知道普通队列是限制级的一端进,另一端出的FIFO形式,栈是一端进出的LIFO形式,而双端队列就没有这样的限制级,也就是我们可以在 队列两端进行插入或者...

选一个简单的数据结构聊一聊,话说有很多数据结构都在玩组合拳,比如说:块状链表,块状数组,当然还有本篇的双端队列,是的,它就是

栈和队列的组合体。

一:概念

     我们知道普通队列是限制级的一端进,另一端出的FIFO形式,栈是一端进出的LIFO形式,而双端队列就没有这样的限制级,也就是我们可以在

队列两端进行插入或者删除操作。

二:编码

1:定义结构体

    通常情况下,队列的内部都是采用数组来实现,而且带有两个指针head和tail来指向数组的区间段,为了充分利用数组空间,我们也会用%来实

现逻辑上的循环数组,如下图。

 


  
  1. public class MyQueue
  2. {
  3. public int head;
  4. public int tail;
  5. public int maxSize;
  6. public int size;
  7. public T[] list;
  8. public MyQueue()
  9. {
  10. head = tail = size = 0;
  11. maxSize = 3;
  12. list = new T[maxSize];
  13. }
  14. }

 

这里有一个注意的细节就是“size字段“,它是为了方便统计队列是否为满或者队列是否为空。

2:队尾入队

    刚才也说了,双端队列是可以在队列的两端进行插入和删除的,要注意的是我们用head和tail指针的时候,tail指针是指向元素的下一个位置,

而head指针是指向当前元素,所以我们可以从tail端push数据的时候只要”顺时针“下移一个位置即可。


  
  1. /// <summary>
  2. /// 队尾入队
  3. /// </summary>
  4. /// <param name="t"></param>
  5. /// <returns></returns>
  6. public bool Push_Tail(T t)
  7. {
  8. //判断队列是否已满
  9. if (myQueue.size == myQueue.list.Length)
  10. return false;
  11. myQueue.list[myQueue.tail] = t;
  12. //顺时针旋转
  13. myQueue.tail = (myQueue.tail + 1) % myQueue.maxSize;
  14. myQueue.size++;
  15. return true;
  16. }

 


3:队尾出队

    和队尾入队一样,我们只要将tail指针”逆时针“下移一个位置,当然有一个细节需要注意,就是tail指针有存在负值的情况,毕竟我们是做”--操作“的,

所以需要tail+maxSize,即:myQueue.tail = (--myQueue.tail + myQueue.maxSize) % myQueue.maxSize;


  
  1. /// <summary>
  2. /// 队尾出队
  3. /// </summary>
  4. /// <param name="edges"></param>
  5. /// <param name="t"></param>
  6. public T Pop_Tail()
  7. {
  8. //判断队列是否已空
  9. if (myQueue.size == 0)
  10. return default(T);
  11. //逆时针旋转(防止负数)
  12. myQueue.tail = (--myQueue.tail + myQueue.maxSize) % myQueue.maxSize;
  13. var temp = myQueue.list[myQueue.tail];
  14. //赋予空值
  15. myQueue.list[myQueue.tail] = default(T);
  16. myQueue.size--;
  17. return temp;
  18. }

 

4:队首入队

    从head端来说,我们push数据的时候是head指针“逆时针”旋转,要注意的是同样要防止负数的产生,并且head指针是指向当前元素。


  
  1. /// <summary>
  2. /// 队首入队
  3. /// </summary>
  4. /// <param name="t"></param>
  5. /// <returns></returns>
  6. public bool Push_Head(T t)
  7. {
  8. //判断队列是否已满
  9. if (myQueue.size == myQueue.list.Length)
  10. return false;
  11. //逆时针旋转(防止负数产生)
  12. myQueue.head = (--myQueue.head + myQueue.maxSize) % myQueue.maxSize;
  13. //赋予元素
  14. myQueue.list[myQueue.head] = t;
  15. myQueue.size++;
  16. return true;
  17. }

 

 

5:队首出队

    说到这个方法,我想大家应该都懂了双端队列的大概流程了,这个方法我也不用赘叙了。


  
  1. /// <summary>
  2. /// 队首出队
  3. /// </summary>
  4. /// <param name="edges"></param>
  5. /// <param name="t"></param>
  6. public T Pop_Head()
  7. {
  8. //判断队列是否已空
  9. if (myQueue.size == 0)
  10. return default(T);
  11. //获取队首元素
  12. var temp = myQueue.list[myQueue.head];
  13. //原来单位的值赋默认值
  14. myQueue.list[myQueue.head] = default(T);
  15. //顺时针旋转
  16. myQueue.head = (myQueue.head + 1) % myQueue.maxSize;
  17. myQueue.size--;
  18. return temp;
  19. }

 

从上面的四个方法可以看出:

 

当我们只使用Push_Tail和Pop_Tail的话,那它就是栈。

当我们只使用Push_Tail和Pop_Head的话,那它就是队列。

最后是全部代码:

 


  
  1. using System.Net;
  2. using System;
  3. using System.IO;
  4. using System.Collections.Generic;
  5. using System.Text;
  6. using System.Drawing;
  7. using System.Drawing.Imaging;
  8. class Program
  9. {
  10. static void Main(string[] args)
  11. {
  12. DoubleQueue<int> queue = new DoubleQueue<int>();
  13. queue.Push_Tail(10);
  14. queue.Push_Tail(20);
  15. queue.Push_Tail(30);
  16. queue.Pop_Tail();
  17. queue.Pop_Tail();
  18. queue.Pop_Tail();
  19. queue.Push_Tail(10);
  20. queue.Push_Head(20);
  21. queue.Push_Head(30);
  22. queue.Push_Head(30);
  23. queue.Pop_Tail();
  24. queue.Pop_Tail();
  25. queue.Pop_Head();
  26. queue.Push_Head(40);
  27. queue.Push_Tail(50);
  28. queue.Push_Tail(60);
  29. }
  30. }
  31. /// <summary>
  32. /// 双端队列
  33. /// </summary>
  34. public class DoubleQueue<T>
  35. {
  36. public class MyQueue
  37. {
  38. public int head;
  39. public int tail;
  40. public int maxSize;
  41. public int size;
  42. public T[] list;
  43. public MyQueue()
  44. {
  45. head = tail = size = 0;
  46. maxSize = 3;
  47. list = new T[maxSize];
  48. }
  49. }
  50. MyQueue myQueue = new MyQueue();
  51. /// <summary>
  52. /// 队尾入队
  53. /// </summary>
  54. /// <param name="t"></param>
  55. /// <returns></returns>
  56. public bool Push_Tail(T t)
  57. {
  58. //判断队列是否已满
  59. if (myQueue.size == myQueue.list.Length)
  60. return false;
  61. myQueue.list[myQueue.tail] = t;
  62. //顺时针旋转
  63. myQueue.tail = (myQueue.tail + 1) % myQueue.maxSize;
  64. myQueue.size++;
  65. return true;
  66. }
  67. /// <summary>
  68. /// 队尾出队
  69. /// </summary>
  70. /// <param name="edges"></param>
  71. /// <param name="t"></param>
  72. public T Pop_Tail()
  73. {
  74. //判断队列是否已空
  75. if (myQueue.size == 0)
  76. return default(T);
  77. //逆时针旋转(防止负数)
  78. myQueue.tail = (--myQueue.tail + myQueue.maxSize) % myQueue.maxSize;
  79. var temp = myQueue.list[myQueue.tail];
  80. //赋予空值
  81. myQueue.list[myQueue.tail] = default(T);
  82. myQueue.size--;
  83. return temp;
  84. }
  85. /// <summary>
  86. /// 队首入队
  87. /// </summary>
  88. /// <param name="t"></param>
  89. /// <returns></returns>
  90. public bool Push_Head(T t)
  91. {
  92. //判断队列是否已满
  93. if (myQueue.size == myQueue.list.Length)
  94. return false;
  95. //逆时针旋转(防止负数产生)
  96. myQueue.head = (--myQueue.head + myQueue.maxSize) % myQueue.maxSize;
  97. //赋予元素
  98. myQueue.list[myQueue.head] = t;
  99. myQueue.size++;
  100. return true;
  101. }
  102. /// <summary>
  103. /// 队首出队
  104. /// </summary>
  105. /// <param name="edges"></param>
  106. /// <param name="t"></param>
  107. public T Pop_Head()
  108. {
  109. //判断队列是否已空
  110. if (myQueue.size == 0)
  111. return default(T);
  112. //获取队首元素
  113. var temp = myQueue.list[myQueue.head];
  114. //原来单位的值赋默认值
  115. myQueue.list[myQueue.head] = default(T);
  116. //顺时针旋转
  117. myQueue.head = (myQueue.head + 1) % myQueue.maxSize;
  118. myQueue.size--;
  119. return temp;
  120. }
  121. }

 

文章来源: blog.csdn.net,作者:网奇,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/jacke121/article/details/116324858

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。