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

2 /// 队尾入队
3 ///

4 /// 5 ///
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 ///

2 /// 队尾出队
3 ///

4 /// 5 /// 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 ///

2 /// 队首入队
3 ///

4 /// 5 ///
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 ///

2 /// 队首出队
3 ///

4 /// 5 /// 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 的话,那它就是伫列。
最后是全部程式码:

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 queue = new DoubleQueue();
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 ///

39 /// 双端伫列
40 ///

41 public class DoubleQueue
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 ///

66 /// 队尾入队
67 ///

68 /// 69 ///
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 ///

87 /// 队尾出队
88 ///

89 /// 90 /// 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 ///

111 /// 队首入队
112 ///

113 /// 114 ///
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 ///

133 /// 队首出队
134 ///

135 /// 136 /// 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 }

文章来自互联网博客网站,版权归作者所有。