概要
本章和介绍"栈"时的流程一样,先对队列进行介绍,然后分别给出队列的C、C++和Java三种语言的实现。内容包括:
1. 队列的介绍
2. 队列的C实现
3. 队列的C++实现
4. 队列的Java实现
转载请注明出处: http://www.cnblogs.com/skywang12345/p/3562279.html
更多内容: 数据结构与算法系列 目录
队列(Queue),是一种线性存储结构。它有以下几个特点:
(01) 队列中数据是按照"先进先出(FIFO, First-In-First-Out)"方式进出队列的。
(02) 队列只允许在"队首"进行删除操作,而在"队尾"进行插入操作。
队列通常包括的两种操作: 入队列 和 出队列 。
1. 队列的示意图
队列中有10,20,30共3个数据。
2. 出队列
出队列前 :队首是10,队尾是30。
出队列后 :出队列(队首)之后。队首是20,队尾是30。
3. 入队列
入队列前 :队首是20,队尾是30。
入队列后 :40入队列(队尾)之后。队首是20,队尾是40。
下面介绍队列的实现,分别介绍C/C++/Java三种实现
共介绍4种C语言实现。
1. C语言实现一:数组实现的队列,并且只能存储int数据。
2. C语言实现二:单向链表实现的队列,并且只能存储int数据。
3. C语言实现三:双向链表实现的队列,并且只能存储int数据。
4. C语言实现四:双向链表实现的队列,能存储任意类型的数据。
1. C语言实现一:数组实现的队列,并且只能存储int数据
实现代码( array_queue.c)
1 #include <stdio.h>
2 #include <malloc.h>
3
4 /**
5 * C 语言: 数组实现的队列,只能存储int数据。
6 *
7 * @author skywang
8 * @date 2013/11/07
9 */
10
11 // 保存数据的数组
12 static int *arr=NULL;
13 // 队列的实际大小
14 static int count;
15
16 // 创建“队列”
17 int create_array_queue(int sz)
18 {
19 arr = (int *)malloc(sz*sizeof(int));
20 if (!arr)
21 {
22 printf("arr malloc error!");
23 return -1;
24 }
25 count = 0;
26
27 return 0;
28 }
29
30 // 销毁“队列”
31 int destroy_array_queue()
32 {
33 if (arr)
34 {
35 free(arr);
36 arr = NULL;
37 }
38
39 return 0;
40 }
41
42 // 将val添加到队列的末尾
43 void add(int val)
44 {
45 arr[count++] = val;
46 }
47
48 // 返回“队列开头元素”
49 int front()
50 {
51 return arr[0];
52 }
53
54 // 返回并删除“队列开头元素”
55 int pop()
56 {
57 int i = 0;;
58 int ret = arr[0];
59
60 count--;
61 while (i++<count)
62 arr[i-1] = arr[i];
63
64 return ret;
65 }
66
67 // 返回“队列”的大小
68 int size()
69 {
70 return count;
71 }
72
73 // 返回“队列”是否为空
74 int is_empty()
75 {
76 return count==0;
77 }
78
79 void main()
80 {
81 int tmp=0;
82
83 // 创建“队列”
84 create_array_queue(12);
85
86 // 将10, 20, 30 依次推入队列中
87 add(10);
88 add(20);
89 add(30);
90
91 // 将“队列开头的元素”赋值给tmp,并删除“该元素”
92 tmp = pop();
93 printf("tmp=%d\n", tmp);
94
95 // 只将“队列开头的元素”赋值给tmp,不删除该元素.
96 tmp = front();
97 printf("tmp=%d\n", tmp);
98
99 add(40);
100
101 // 打印队列
102 printf("is_empty()=%d\n", is_empty());
103 printf("size()=%d\n", size());
104 while (!is_empty())
105 {
106 printf("%d\n", pop());
107 }
108
109 // 销毁队列
110 destroy_array_queue();
111 }
View Code
运行结果 :
tmp=10 tmp=20 is_empty()=0 size()=3 20 30 40
结果说明 : 该示例中的队列,是通过"数组"来实现的!
由于代码中已经给出了详细了注释,这里就不再对函数进行说明了。仅对主函数main的逻辑进行简单介绍。
(01) 在主函数main中,先将 "10, 20, 30"依次入队列。此时,队列的数据是: 10 --> 20 --> 30
(02) 接着通过pop()返回队首元素;pop()操作并不会改变队列中的数据。此时,队列的数据依然是: 10 --> 20 --> 30
(03) 接着通过front()返回并删除队首元素。front()操作之后,队列的数据是: 10 --> 30
(04) 接着通过add(40)将40入队列。add(40)操作之后,队列中的数据是: 10 --> 20 --> 40
2. C语言实现二:单向链表实现的队列,并且只能存储int数据
实现代码( slink_queue.c)
1 #include <stdio.h> 2 #include <malloc.h> 3 4 /** 5 * C 语言: 单链表实现“队列”,只能存储int数据。 6 * 7 * @author skywang 8 * @date 2013/11/07 9 */ 10 11 // 单链表节点 12 struct node { 13 int val; 14 struct node* next; 15 }; 16 17 // 表头 18 static struct node *phead=NULL; 19 20 // 创建节点,val为节点值 21 static struct node* create_node(val) 22 { 23 struct node *pnode=NULL; 24 pnode = (struct node*)malloc(sizeof(struct node)); 25 if (!pnode) 26 return NULL; 27 pnode->val = val; 28 pnode->next = NULL; 29 30 return pnode; 31 } 32 33 // 销毁单向链表 34 static int destroy_single_link() 35 { 36 struct node *pnode=NULL; 37 38 while (phead != NULL) 39 { 40 pnode = phead; 41 phead = phead->next; 42 free(pnode); 43 } 44 return 0; 45 } 46 47 // 将val添加到队列的末尾 48 static void add(int val) 49 { 50 if (!phead) 51 { 52 phead = create_node(val); 53 return ; 54 } 55 56 struct node *pnode = create_node(val); 57 struct node *pend = phead; 58 while (pend->next) 59 pend = pend->next; 60 61 pend->next = pnode; 62 } 63 64 // 返回“队列开头元素” 65 int front() 66 { 67 return phead->val; 68 } 69 70 // 返回并删除“队列开头元素” 71 static int pop() 72 { 73 int ret = phead->val; 74 struct node *pnode = phead; 75 76 phead = phead->next; 77 free(pnode); 78 79 return ret; 80 } 81 82 // 返回链表中节点的个数 83 static int size() 84 { 85 int count=0; 86 struct node *pend = phead; 87 88 while (pend) 89 { 90 pend = pend->next; 91 count++; 92 } 93 94 return count; 95 } 96 97 // 链表是否为空 98 static int is_empty() 99 { 100 return size()==0; 101 } 102 103 void main() 104 { 105 int tmp=0; 106 107 // 将10, 20, 30 依次加入到队列中 108 add(10); 109 add(20); 110 add(30); 111 112 // 将“队列开头元素”赋值给tmp,并删除“该元素” 113 tmp = pop(); 114 printf("tmp=%d\n", tmp); 115 116 // 只将“队列开头的元素”赋值给tmp,不删除该元素. 117 tmp = front(); 118 printf("tmp=%d\n", tmp); 119 120 add(40); 121 122 printf("is_empty()=%d\n", is_empty()); 123 printf("size()=%d\n", size()); 124 while (!is_empty()) 125 { 126 printf("%d\n", pop()); 127 } 128 129 // 销毁队列 130 destroy_single_link(); 131 }View Code
代码说明 : "运行结果" 以及 "主函数main的逻辑"都和"C语言实现一"的一样。 不同的是,该示例中的队列是通过单向链表实现的。
3. C语言实现三:双向链表实现的队列,并且只能存储int数据
实现代码
双向链表的头文件( double_link.h)
1 #ifndef _DOUBLE_LINK_H 2 #define _DOUBLE_LINK_H 3 4 // 新建“双向链表”。成功,返回表头;否则,返回NULL 5 extern int create_dlink(); 6 // 撤销“双向链表”。成功,返回0;否则,返回-1 7 extern int destroy_dlink(); 8 9 // “双向链表是否为空”。为空的话返回1;否则,返回0。 10 extern int dlink_is_empty(); 11 // 返回“双向链表的大小” 12 extern int dlink_size(); 13 14 // 获取“双向链表中第index位置的元素的值”。成功,返回节点值;否则,返回-1。 15 extern int dlink_get(int index); 16 // 获取“双向链表中第1个元素的值”。成功,返回节点值;否则,返回-1。 17 extern int dlink_get_first(); 18 // 获取“双向链表中最后1个元素的值”。成功,返回节点值;否则,返回-1。 19 extern int dlink_get_last(); 20 21 // 将“value”插入到index位置。成功,返回0;否则,返回-1。 22 extern int dlink_insert(int index, int value); 23 // 将“value”插入到表头位置。成功,返回0;否则,返回-1。 24 extern int dlink_insert_first(int value); 25 // 将“value”插入到末尾位置。成功,返回0;否则,返回-1。 26 extern int dlink_append_last(int value); 27 28 // 删除“双向链表中index位置的节点”。成功,返回0;否则,返回-1 29 extern int dlink_delete(int index); 30 // 删除第一个节点。成功,返回0;否则,返回-1 31 extern int dlink_delete_first(); 32 // 删除组后一个节点。成功,返回0;否则,返回-1 33 extern int dlink_delete_last(); 34 35 // 打印“双向链表” 36 extern void print_dlink(); 37 38 #endifView Code
双向链表的实现文件( double_link.c)
1 #include <stdio.h> 2 #include <malloc.h> 3 4 /** 5 * C 语言: 双向链表,只能存储int数据。 6 * 7 * @author skywang 8 * @date 2013/11/07 9 */ 10 11 // 双向链表节点 12 typedef struct tag_node 13 { 14 struct tag_node *prev; 15 struct tag_node *next; 16 int value; 17 }node; 18 19 // 表头。注意,表头不存放元素值!!! 20 static node *phead=NULL; 21 // 节点个数。 22 static int count=0; 23 24 // 新建“节点”。成功,返回节点指针;否则,返回NULL。 25 static node* create_node(int value) 26 { 27 node *pnode=NULL; 28 pnode = (node *)malloc(sizeof(node)); 29 if (!pnode) 30 { 31 printf("create node error!\n"); 32 return NULL; 33 } 34 // 默认的,pnode的前一节点和后一节点都指向它自身 35 pnode->prev = pnode->next = pnode; 36 // 节点的值为value 37 pnode->value = value; 38 39 return pnode; 40 } 41 42 // 新建“双向链表”。成功,返回0;否则,返回-1。 43 int create_dlink() 44 { 45 // 创建表头 46 phead = create_node(-1); 47 if (!phead) 48 return -1; 49 50 // 设置“节点个数”为0 51 count = 0; 52 53 return 0; 54 } 55 56 // “双向链表是否为空” 57 int dlink_is_empty() 58 { 59 return count == 0; 60 } 61 62 // 返回“双向链表的大小” 63 int dlink_size() { 64 return count; 65 } 66 67 // 获取“双向链表中第index位置的节点” 68 static node* get_node(int index) 69 { 70 if (index<0 || index>=count) 71 { 72 printf("%s failed! the index in out of bound!\n", __func__); 73 return NULL; 74 } 75 76 // 正向查找 77 if (index <= (count/2)) 78 { 79 int i=0; 80 node *pnode=phead->next; 81 while ((i++) < index) 82 pnode = pnode->next; 83 84 return pnode; 85 } 86 87 // 反向查找 88 int j=0; 89 int rindex = count - index - 1; 90 node *rnode=phead->prev; 91 while ((j++) < rindex) 92 rnode = rnode->prev; 93 94 return rnode; 95 } 96 97 // 获取“第一个节点” 98 static node* get_first_node() 99 { 100 return get_node(0); 101 } 102 103 // 获取“最后一个节点” 104 static node* get_last_node() 105 { 106 return get_node(count-1); 107 } 108 109 // 获取“双向链表中第index位置的元素的值”。成功,返回节点值;否则,返回-1。 110 int dlink_get(int index) 111 { 112 node *pindex=get_node(index); 113 if (!pindex) 114 { 115 printf("%s failed!\n", __func__); 116 return -1; 117 } 118 119 return pindex->value; 120 121 } 122 123 // 获取“双向链表中第1个元素的值” 124 int dlink_get_first() 125 { 126 return dlink_get(0); 127 } 128 129 // 获取“双向链表中最后1个元素的值” 130 int dlink_get_last() 131 { 132 return dlink_get(count-1); 133 } 134 135 // 将“value”插入到index位置。成功,返回0;否则,返回-1。 136 int dlink_insert(int index, int value) 137 { 138 // 插入表头 139 if (index==0) 140 return dlink_insert_first(value); 141 142 // 获取要插入的位置对应的节点 143 node *pindex=get_node(index); 144 if (!pindex) 145 return -1; 146 147 // 创建“节点” 148 node *pnode=create_node(value); 149 if (!pnode) 150 return -1; 151 152 pnode->prev = pindex->prev; 153 pnode->next = pindex; 154 pindex->prev->next = pnode; 155 pindex->prev = pnode; 156 // 节点个数+1 157 count++; 158 159 return 0; 160 } 161 162 // 将“value”插入到表头位置 163 int dlink_insert_first(int value) 164 { 165 node *pnode=create_node(value); 166 if (!pnode) 167 return -1; 168 169 pnode->prev = phead; 170 pnode->next = phead->next; 171 phead->next->prev = pnode; 172 phead->next = pnode; 173 count++; 174 return 0; 175 } 176 177 // 将“value”插入到末尾位置 178 int dlink_append_last(int value) 179 { 180 node *pnode=create_node(value); 181 if (!pnode) 182 return -1; 183 184 pnode->next = phead; 185 pnode->prev = phead->prev; 186 phead->prev->next = pnode; 187 phead->prev = pnode; 188 count++; 189 return 0; 190 } 191 192 // 删除“双向链表中index位置的节点”。成功,返回0;否则,返回-1。 193 int dlink_delete(int index) 194 { 195 node *pindex=get_node(index); 196 if (!pindex) 197 { 198 printf("%s failed! the index in out of bound!\n", __func__); 199 return -1; 200 } 201 202 pindex->next->prev = pindex->prev; 203 pindex->prev->next = pindex->next; 204 free(pindex); 205 count--; 206 207 return 0; 208 } 209 210 // 删除第一个节点 211 int dlink_delete_first() 212 { 213 return dlink_delete(0); 214 } 215 216 // 删除组后一个节点 217 int dlink_delete_last() 218 { 219 return dlink_delete(count-1); 220 } 221 222 // 撤销“双向链表”。成功,返回0;否则,返回-1。 223 int destroy_dlink() 224 { 225 if (!phead) 226 { 227 printf("%s failed! dlink is null!\n", __func__); 228 return -1; 229 } 230 231 node *pnode=phead->next; 232 node *ptmp=NULL; 233 while(pnode != phead) 234 { 235 ptmp = pnode; 236 pnode = pnode->next; 237 free(ptmp); 238 } 239 240 free(phead); 241 phead = NULL; 242 count = 0; 243 244 return 0; 245 } 246 247 // 打印“双向链表” 248 void print_dlink() 249 { 250 if (count==0 || (!phead)) 251 { 252 printf("%s dlink is empty!\n", __func__); 253 return ; 254 } 255 256 printf("%s dlink size()=%d\n", __func__, count); 257 node *pnode=phead->next; 258 while(pnode != phead) 259 { 260 printf("%d\n", pnode->value); 261 pnode = pnode->next; 262 } 263 }View Code
双向链表的测试程序( dlink_queue.c)
1 #include <stdio.h>
2 #include "double_link.h"
3
4 /**
5 * C 语言: 双向链表实现“队列”,只能存储int数据。
6 *
7 * @author skywang
8 * @date 2013/11/07
9 */
10
11 // 创建队列
12 int create_dlink_queue()
13 {
14 return create_dlink();
15 }
16
17 // 销毁队列
18 int destroy_dlink_queue()
19 {
20 return destroy_dlink();
21 }
22
23 // 将val添加到队列的末尾
24 int add(int val)
25 {
26 return dlink_append_last(val);
27 }
28
29 // 返回“队列开头元素”
30 int front()
31 {
32 return dlink_get_first();
33 }
34
35 // 返回并删除“队列开头元素”
36 int pop()
37 {
38 int ret = dlink_get_first();
39 dlink_delete_first();
40 return ret;
41 }
42
43 // 返回“队列”的大小
44 int size()
45 {
46 return dlink_size();
47 }
48
49 // 返回“队列”是否为空
50 int is_empty()
51 {
52 return dlink_is_empty();
53 }
54
55 void main()
56 {
57 int tmp=0;
58
59 // 创建“队列”
60 create_dlink_queue();
61
62 // 将10, 20, 30 依次队列中
63 add(10);
64 add(20);
65 add(30);
66
67 // 将“队列开头的元素”赋值给tmp,并删除“该元素”
68 tmp = pop();
69 printf("tmp=%d\n", tmp);
70
71 // 只将“队列开头的元素”赋值给tmp,不删除该元素.
72 tmp = front();
73 printf("tmp=%d\n", tmp);
74
75 add(40);
76
77 printf("is_empty()=%d\n", is_empty());
78 printf("size()=%d\n", size());
79 while (!is_empty())
80 {
81 printf("%d\n", pop());
82 }
83
84 // 销毁队列
85 destroy_dlink_queue();
86 }
View Code
代码说明 : "运行结果" 以及 "主函数main的逻辑"都和前两个示例的一样。 不同的是,该示例中的队列是通过双向链表实现的。
4. C语言实现四:双向链表实现的队列,能存储任意类型的数据
实现代码
双向链表的头文件( double_link.h)
1 #ifndef _DOUBLE_LINK_H 2 #define _DOUBLE_LINK_H 3 4 // 新建“双向链表”。成功,返回表头;否则,返回NULL 5 extern int create_dlink(); 6 // 撤销“双向链表”。成功,返回0;否则,返回-1 7 extern int destroy_dlink(); 8 9 // “双向链表是否为空”。为空的话返回1;否则,返回0。 10 extern int dlink_is_empty(); 11 // 返回“双向链表的大小” 12 extern int dlink_size(); 13 14 // 获取“双向链表中第index位置的元素”。成功,返回节点指针;否则,返回NULL。 15 extern void* dlink_get(int index); 16 // 获取“双向链表中第1个元素”。成功,返回节点指针;否则,返回NULL。 17 extern void* dlink_get_first(); 18 // 获取“双向链表中最后1个元素”。成功,返回节点指针;否则,返回NULL。 19 extern void* dlink_get_last(); 20 21 // 将“value”插入到index位置。成功,返回0;否则,返回-1。 22 extern int dlink_insert(int index, void *pval); 23 // 将“value”插入到表头位置。成功,返回0;否则,返回-1。 24 extern int dlink_insert_first(void *pval); 25 // 将“value”插入到末尾位置。成功,返回0;否则,返回-1。 26 extern int dlink_append_last(void *pval); 27 28 // 删除“双向链表中index位置的节点”。成功,返回0;否则,返回-1 29 extern int dlink_delete(int index); 30 // 删除第一个节点。成功,返回0;否则,返回-1 31 extern int dlink_delete_first(); 32 // 删除组后一个节点。成功,返回0;否则,返回-1 33 extern int dlink_delete_last(); 34 35 #endifView Code
双向链表的实现文件( double_link.c)
1 #include <stdio.h>
2 #include <malloc.h>
3
4 /**
5 * C 语言: 双向链表,能存储任意数据。
6 *
7 * @author skywang
8 * @date 2013/11/07
9 */
10
11 // 双向链表节点
12 typedef struct tag_node
13 {
14 struct tag_node *prev;
15 struct tag_node *next;
16 void* p;
17 }node;
18
19 // 表头。注意,表头不存放元素值!!!
20 static node *phead=NULL;
21 // 节点个数。
22 static int count=0;
23
24 // 新建“节点”。成功,返回节点指针;否则,返回NULL。
25 static node* create_node(void *pval)
26 {
27 node *pnode=NULL;
28 pnode = (node *)malloc(sizeof(node));
29 if (!pnode)
30 {
31 printf("create node error!\n");
32 return NULL;
33 }
34 // 默认的,pnode的前一节点和后一节点都指向它自身
35 pnode->prev = pnode->next = pnode;
36 // 节点的值为pval
37 pnode->p = pval;
38
39 return pnode;
40 }
41
42 // 新建“双向链表”。成功,返回0;否则,返回-1。
43 int create_dlink()
44 {
45 // 创建表头
46 phead = create_node(NULL);
47 if (!phead)
48 return -1;
49
50 // 设置“节点个数”为0
51 count = 0;
52
53 return 0;
54 }
55
56 // “双向链表是否为空”
57 int dlink_is_empty()
58 {
59 return count == 0;
60 }
61
62 // 返回“双向链表的大小”
63 int dlink_size() {
64 return count;
65 }
66
67 // 获取“双向链表中第index位置的节点”
68 static node* get_node(int index)
69 {
70 if (index<0 || index>=count)
71 {
72 printf("%s failed! index out of bound!\n", __func__);
73 return NULL;
74 }
75
76 // 正向查找
77 if (index <= (count/2))
78 {
79 int i=0;
80 node *pnode=phead->next;
81 while ((i++) < index)
82 pnode = pnode->next;
83
84 return pnode;
85 }
86
87 // 反向查找
88 int j=0;
89 int rindex = count - index - 1;
90 node *rnode=phead->prev;
91 while ((j++) < rindex)
92 rnode = rnode->prev;
93
94 return rnode;
95 }
96
97 // 获取“第一个节点”
98 static node* get_first_node()
99 {
100 return get_node(0);
101 }
102
103 // 获取“最后一个节点”
104 static node* get_last_node()
105 {
106 return get_node(count-1);
107 }
108
109 // 获取“双向链表中第index位置的元素”。成功,返回节点值;否则,返回-1。
110 void* dlink_get(int index)
111 {
112 node *pindex=get_node(index);
113 if (!pindex)
114 {
115 printf("%s failed!\n", __func__);
116 return NULL;
117 }
118
119 return pindex->p;
120
121 }
122
123 // 获取“双向链表中第1个元素的值”
124 void* dlink_get_first()
125 {
126 return dlink_get(0);
127 }
128
129 // 获取“双向链表中最后1个元素的值”
130 void* dlink_get_last()
131 {
132 return dlink_get(count-1);
133 }
134
135 // 将“pval”插入到index位置。成功,返回0;否则,返回-1。
136 int dlink_insert(int index, void* pval)
137 {
138 // 插入表头
139 if (index==0)
140 return dlink_insert_first(pval);
141
142 // 获取要插入的位置对应的节点
143 node *pindex=get_node(index);
144 if (!pindex)
145 return -1;
146
147 // 创建“节点”
148 node *pnode=create_node(pval);
149 if (!pnode)
150 return -1;
151
152 pnode->prev = pindex->prev;
153 pnode->next = pindex;
154 pindex->prev->next = pnode;
155 pindex->prev = pnode;
156 // 节点个数+1
157 count++;
158
159 return 0;
160 }
161
162 // 将“pval”插入到表头位置
163 int dlink_insert_first(void *pval)
164 {
165 node *pnode=create_node(pval);
166 if (!pnode)
167 return -1;
168
169 pnode->prev = phead;
170 pnode->next = phead->next;
171 phead->next->prev = pnode;
172 phead->next = pnode;
173 count++;
174 return 0;
175 }
176
177 // 将“pval”插入到末尾位置
178 int dlink_append_last(void *pval)
179 {
180 node *pnode=create_node(pval);
181 if (!pnode)
182 return -1;
183
184 pnode->next = phead;
185 pnode->prev = phead->prev;
186 phead->prev->next = pnode;
187 phead->prev = pnode;
188 count++;
189 return 0;
190 }
191
192 // 删除“双向链表中index位置的节点”。成功,返回0;否则,返回-1。
193 int dlink_delete(int index)
194 {
195 node *pindex=get_node(index);
196 if (!pindex)
197 {
198 printf("%s failed! the index in out of bound!\n", __func__);
199 return -1;
200 }
201
202 pindex->next->prev = pindex->prev;
203 pindex->prev->next = pindex->next;
204 free(pindex);
205 count--;
206
207 return 0;
208 }
209
210 // 删除第一个节点
211 int dlink_delete_first()
212 {
213 return dlink_delete(0);
214 }
215
216 // 删除组后一个节点
217 int dlink_delete_last()
218 {
219 return dlink_delete(count-1);
220 }
221
222 // 撤销“双向链表”。成功,返回0;否则,返回-1。
223 int destroy_dlink()
224 {
225 if (!phead)
226 {
227 printf("%s failed! dlink is null!\n", __func__);
228 return -1;
229 }
230
231 node *pnode=phead->next;
232 node *ptmp=NULL;
233 while(pnode != phead)
234 {
235 ptmp = pnode;
236 pnode = pnode->next;
237 free(ptmp);
238 }
239
240 free(phead);
241 phead = NULL;
242 count = 0;
243
244 return 0;
245 }
View Code
双向链表的测试程序( dlink_queue.c)
1 #include <stdio.h>
2 #include "double_link.h"
3
4 /**
5 * C 语言: 双向链表实现“队列”,能存储任意数据。
6 *
7 * @author skywang
8 * @date 2013/11/07
9 */
10
11 // 创建队列
12 int create_dlink_queue()
13 {
14 return create_dlink();
15 }
16
17 // 销毁队列
18 int destroy_dlink_queue()
19 {
20 return destroy_dlink();
21 }
22
23 // 将p添加到队列的末尾
24 int add(void *p)
25 {
26 return dlink_append_last(p);
27 }
28
29 // 返回“队列开头元素”
30 void* front()
31 {
32 return dlink_get_first();
33 }
34
35 // 返回“队列开头的元素”,并删除“该元素”
36 void* pop()
37 {
38 void *p = dlink_get_first();
39 dlink_delete_first();
40 return p;
41 }
42
43 // 返回“队列”的大小
44 int size()
45 {
46 return dlink_size();
47 }
48
49 // 返回“队列”是否为空
50 int is_empty()
51 {
52 return dlink_is_empty();
53 }
54
55
56 typedef struct tag_stu
57 {
58 int id;
59 char name[20];
60 }stu;
61
62 static stu arr_stu[] =
63 {
64 {10, "sky"},
65 {20, "jody"},
66 {30, "vic"},
67 {40, "dan"},
68 };
69 #define ARR_STU_SIZE ( (sizeof(arr_stu)) / (sizeof(arr_stu[0])) )
70
71 static void print_stu(stu *p)
72 {
73 if (!p)
74 return ;
75
76 printf("id=%d, name=%s\n", p->id, p->name);
77 }
78
79 void main()
80 {
81 stu *pval=NULL;
82
83 // 创建“队列”
84 create_dlink_queue();
85
86 // 将10, 20, 30 依次推入队列中
87 int i=0;
88 for (i=0; i<ARR_STU_SIZE-1; i++)
89 {
90 add(&arr_stu[i]);
91 }
92
93 // 将“队列开头的元素”赋值给tmp,并删除“该元素”
94 pval = (stu*)pop();
95 print_stu(pval) ;
96
97 // 只将“队列开头的元素”赋值给tmp,不删除该元素.
98 pval = front();
99 print_stu(pval) ;
100
101 add(&arr_stu[ARR_STU_SIZE-1]);
102
103 printf("is_empty()=%d\n", is_empty());
104 printf("size()=%d\n", size());
105 // 打印队列中的所有元素
106 while (!is_empty())
107 {
108 pval = pop();
109 print_stu(pval) ;
110 }
111
112 // 销毁队列
113 destroy_dlink_queue();
114 }
View Code
运行结果 :
id=10, name=sky id=20, name=jody is_empty()=0 size()=3 id=20, name=jody id=30, name=vic id=40, name=dan
结果说明 : 该示例中的队列是通过双向链表实现的,并且能存储任意类型的数据。
C++的STL中本身就包含了list类,基本上该list类就能满足我们的需求,所以很少需要我们自己来实现。 本部分介绍2种C++实现。
1. C++实现一:数组实现的队列,能存储任意类型的数据。
2. C++实现二:C++的 STL 中自带的"队列"(list)的示例。
1. C++实现一:数组实现的队列,能存储任意类型的数据
实现代码
队列的实现文件( ArrayQueue.h)
1 #ifndef ARRAY_QUEUE_HXX
2 #define ARRAY_QUEUE_HXX
3
4 #include <iostream>
5 using namespace std;
6
7 template<class T> class ArrayQueue{
8 public:
9 ArrayQueue();
10 ~ArrayQueue();
11
12 void add(T t);
13 T front();
14 T pop();
15 int size();
16 int is_empty();
17
18 private:
19 T *arr;
20 int count;
21 };
22
23 // 创建“队列”,默认大小是12
24 template<class T>
25 ArrayQueue<T>::ArrayQueue()
26 {
27 arr = new T[12];
28 if (!arr)
29 {
30 cout<<"arr malloc error!"<<endl;
31 }
32 }
33
34 // 销毁“队列”
35 template<class T>
36 ArrayQueue<T>::~ArrayQueue()
37 {
38 if (arr)
39 {
40 delete[] arr;
41 arr = NULL;
42 }
43 }
44
45 // 将val添加到队列的末尾
46 template<class T>
47 void ArrayQueue<T>::add(T t)
48 {
49 arr[count++] = t;
50 }
51
52
53 // 返回“队列开头元素”
54 template<class T>
55 T ArrayQueue<T>::front()
56 {
57 return arr[0];
58 }
59
60 // 返回并删除“队列末尾的元素”
61 template<class T>
62 T ArrayQueue<T>::pop()
63 {
64 int i = 0;;
65 T ret = arr[0];
66
67 count--;
68 while (i++<count)
69 arr[i-1] = arr[i];
70
71 return ret;
72 }
73
74 // 返回“队列”的大小
75 template<class T>
76 int ArrayQueue<T>::size()
77 {
78 return count;
79 }
80
81 // 返回“队列”是否为空
82 template<class T>
83 int ArrayQueue<T>::is_empty()
84 {
85 return count==0;
86 }
87
88
89 #endif
View Code
队列的测试程序( Main.cpp)
1 #include <iostream> 2 #include "ArrayQueue.h" 3 using namespace std; 4 5 /** 6 * C++ : 数组实现“队列”,能存储任意数据。 7 * 8 * @author skywang 9 * @date 2013/11/07 10 */ 11 int main() 12 { 13 int tmp=0; 14 ArrayQueue<int> *astack = new ArrayQueue<int>(); 15 16 // 将10, 20, 30 依次推入队列中 17 astack->add(10); 18 astack->add(20); 19 astack->add(30); 20 21 // 将“队列开头元素”赋值给tmp,并删除“该元素” 22 tmp = astack->pop(); 23 cout<<"tmp="<<tmp<<endl; 24 25 // 只将“队列开头的元素”赋值给tmp,不删除该元素. 26 tmp = astack->front(); 27 cout<<"tmp="<<tmp<<endl; 28 29 astack->add(40); 30 31 cout<<"is_empty()="<<astack->is_empty()<<endl; 32 cout<<"size()="<<astack->size()<<endl; 33 while (!astack->is_empty()) 34 { 35 tmp = astack->pop(); 36 cout<<tmp<<endl; 37 } 38 39 return 0; 40 }View Code
运行结果 :
tmp=10 tmp=20 is_empty()=0 size()=3 20 30 40
结果说明 : 关于"队列的声明和实现都在头文件中"的原因,是因为队列的实现利用了C++模板,而"C++编译器不能支持对模板的分离式编译"。
2. C++实现二:C++的 STL 中自带的"队列"(list)的示例
实现代码( StlQueue.cpp)
1 #include <iostream>
2 #include <queue>
3 using namespace std;
4
5 /**
6 * C++ : STL中的队列(queue)的演示程序。
7 *
8 * @author skywang
9 * @date 2013/11/07
10 */
11 int main ()
12 {
13 int tmp=0;
14 queue<int> iqueue;
15
16 // 将10, 20, 30 依次加入队列的末尾
17 iqueue.push(10);
18 iqueue.push(20);
19 iqueue.push(30);
20
21 // 删除队列开头的元素
22 iqueue.pop();
23
24 // 将“队列开头的元素”赋值给tmp,不删除该元素.
25 tmp = iqueue.front();
26 cout<<"tmp="<<tmp<<endl;
27
28 // 将40加入到队列的末尾
29 iqueue.push(40);
30
31 cout << "empty()=" << iqueue.empty() <<endl;
32 cout << "size()=" << iqueue.size() <<endl;
33 while (!iqueue.empty())
34 {
35 tmp = iqueue.front();
36 cout<<tmp<<endl;
37 iqueue.pop();
38 }
39
40 return 0;
41 }
View Code
运行结果 :
tmp=20
empty()=0
size()=3
20
30
40
和C++一样,JDK包Queue中的也提供了"队列"的实现。JDK中的Queue接口就是"队列",它的实现类也都是队列,用的最多的是LinkedList。 本部分介绍给出2种Java实现
1. Java实现一:数组实现的队列,能存储任意类型的数据。
2. Java实现二:Java的 Collection集合 中自带的"队列"(LinkedList)的示例。
1. Java实现一:数组实现的队列,能存储任意类型的数据
实现代码( ArrayQueue.java)
1 /**
2 * Java : 数组实现“队列”,只能存储int数据。
3 *
4 * @author skywang
5 * @date 2013/11/07
6 */
7 public class ArrayQueue {
8
9 private int[] mArray;
10 private int mCount;
11
12 public ArrayQueue(int sz) {
13 mArray = new int[sz];
14 mCount = 0;
15 }
16
17 // 将val添加到队列的末尾
18 public void add(int val) {
19 mArray[mCount++] = val;
20 }
21
22 // 返回“队列开头元素”
23 public int front() {
24 return mArray[0];
25 }
26
27 // 返回“栈顶元素值”,并删除“栈顶元素”
28 public int pop() {
29 int ret = mArray[0];
30 mCount--;
31 for (int i=1; i<=mCount; i++)
32 mArray[i-1] = mArray[i];
33 return ret;
34 }
35
36 // 返回“栈”的大小
37 public int size() {
38 return mCount;
39 }
40
41 // 返回“栈”是否为空
42 public boolean isEmpty() {
43 return size()==0;
44 }
45
46 public static void main(String[] args) {
47 int tmp=0;
48 ArrayQueue astack = new ArrayQueue(12);
49
50 // 将10, 20, 30 依次推入栈中
51 astack.add(10);
52 astack.add(20);
53 astack.add(30);
54
55 // 将“栈顶元素”赋值给tmp,并删除“栈顶元素”
56 tmp = astack.pop();
57 System.out.printf("tmp=%d\n", tmp);
58
59 // 只将“栈顶”赋值给tmp,不删除该元素.
60 tmp = astack.front();
61 System.out.printf("tmp=%d\n", tmp);
62
63 astack.add(40);
64
65 System.out.printf("isEmpty()=%b\n", astack.isEmpty());
66 System.out.printf("size()=%d\n", astack.size());
67 while (!astack.isEmpty()) {
68 System.out.printf("size()=%d\n", astack.pop());
69 }
70 }
71 }
View Code
运行结果 :
tmp=10 tmp=20 isEmpty()=false size()=3 size()=20 size()=30 size()=40
结果说明 :ArrayQueue是通过数组实现的队列,而且ArrayQueue中使用到了泛型,因此它支持任意类型的数据。
2. Java实现二:Java的 Collection集合 中自带的"队列"(LinkedList)的示例
实现代码( QueueTest.java)
1 import java.util.Stack;
2
3 /**
4 * 用“栈”实现队列
5 *
6 * @author skywang
7 */
8 public class StackList<T> {
9
10 // 向队列添加数据时:(01) 将“已有的全部数据”都移到mIn中。 (02) 将“新添加的数据”添加到mIn中。
11 private Stack<T> mIn = null;
12 // 从队列获取元素时:(01) 将“已有的全部数据”都移到mOut中。(02) 返回并删除mOut栈顶元素。
13 private Stack<T> mOut = null;
14 // 统计计数
15 private int mCount = 0;
16
17 public StackList() {
18 mIn = new Stack<T>();
19 mOut = new Stack<T>();
20 mCount = 0;
21 }
22
23 private void add(T t) {
24 // 将“已有的全部数据”都移到mIn中
25 while (!mOut.empty())
26 mIn.push(mOut.pop());
27
28 // 将“新添加的数据”添加到mIn中
29 mIn.push(t);
30 // 统计数+1
31 mCount++;
32 }
33
34 private T get() {
35 // 将“已有的全部数据”都移到mOut中
36 while (!mIn.empty())
37 mOut.push(mIn.pop());
38 // 统计数-1
39 mCount--;
40
41 // 返回并删除mOut栈顶元素
42 return mOut.pop();
43 }
44
45 private int size() {
46 return mCount;
47 }
48 private boolean isEmpty() {
49 return mCount==0;
50 }
51
52 public static void main(String[] args) {
53 StackList slist = new StackList();
54
55 // 将10, 20, 30 依次推入栈中
56 slist.add(10);
57 slist.add(20);
58 slist.add(30);
59
60 System.out.printf("isEmpty()=%b\n", slist.isEmpty());
61 System.out.printf("size()=%d\n", slist.size());
62 while(!slist.isEmpty()) {
63 System.out.printf("%d\n", slist.get());
64 }
65 }
66 }
View Code
运行结果 :
tmp=10 tmp=20 isEmpty()=false size()=3 tmp=20 tmp=30 tmp=40