继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

经典算法题每日演练——第十九题 双端队列

android开发学习视频
关注TA
已关注
手记 304
粉丝 52
获赞 322

     话说大学的时候老师说妹子比工作重要~,工作可以再换,妹子这个。。。所以。。。这两个月也就一直忙着Fall in love,嗨,慢慢调整心态吧,

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

栈和队列的组合体。

一:概念

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

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

二:编码

1:定义结构体

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

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

复制代码

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

复制代码

这里有一个注意的细节就是“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 12         myQueue.list[myQueue.tail] = t;13 14         //顺时针旋转15         myQueue.tail = (myQueue.tail + 1) % myQueue.maxSize;16 17         myQueue.size++;18 19         return true;20     }

复制代码


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         //逆时针旋转(防止负数)13         myQueue.tail = (--myQueue.tail + myQueue.maxSize) % myQueue.maxSize;14 15         var temp = myQueue.list[myQueue.tail];16 17         //赋予空值18         myQueue.list[myQueue.tail] = default(T);19 20         myQueue.size--;21 22         return temp;23     }

复制代码

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         //逆时针旋转(防止负数产生)13         myQueue.head = (--myQueue.head + myQueue.maxSize) % myQueue.maxSize;14 15         //赋予元素16         myQueue.list[myQueue.head] = t;17 18         myQueue.size++;19 20         return true;21     }

复制代码

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         //获取队首元素13         var temp = myQueue.list[myQueue.head];14 15         //原来单位的值赋默认值16         myQueue.list[myQueue.head] = default(T);17 18         //顺时针旋转19         myQueue.head = (myQueue.head + 1) % myQueue.maxSize;20 21         myQueue.size--;22 23         return temp;24     }

复制代码


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

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

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

最后是全部代码:

View Code

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

 

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP