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

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

     话说大学的时候老师说妹子比工作重要~,工作可以再换,妹子这个。。。所以。。。这两个月也就一直忙着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 }

 

你可能感兴趣的:(算法)