队列的图文解析 和 对应3种语言的实现(C/C++/Java)

 

概要

本章和介绍”“时的流程一样,先对队列进行介绍,然后分别给出队列的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. 队列的示意图

《队列的图文解析 和 对应3种语言的实现(C/C++/Java)》

队列中有10,20,30共3个数据。

 

2. 出队列

《队列的图文解析 和 对应3种语言的实现(C/C++/Java)》

出队列前:队首是10,队尾是30。
出队列后:出队列(队首)之后。队首是20,队尾是30。

 

3. 入队列

《队列的图文解析 和 对应3种语言的实现(C/C++/Java)》

入队列前:队首是20,队尾是30。
入队列后:40入队列(队尾)之后。队首是20,队尾是40。

 

下面介绍队列的实现,分别介绍C/C++/Java三种实现

队列的C实现

共介绍4种C语言实现。
1. C语言实现一:数组实现的队列,并且只能存储int数据。
2. C语言实现二:单向链表实现的队列,并且只能存储int数据。
3. C语言实现三:双向链表实现的队列,并且只能存储int数据。
4. C语言实现四:双向链表实现的队列,能存储任意类型的数据。

 

1. C语言实现一:数组实现的队列,并且只能存储int数据

实现代码(array_queue.c)

《队列的图文解析 和 对应3种语言的实现(C/C++/Java)》
《队列的图文解析 和 对应3种语言的实现(C/C++/Java)》

  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)

《队列的图文解析 和 对应3种语言的实现(C/C++/Java)》
《队列的图文解析 和 对应3种语言的实现(C/C++/Java)》

  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)

《队列的图文解析 和 对应3种语言的实现(C/C++/Java)》
《队列的图文解析 和 对应3种语言的实现(C/C++/Java)》

 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 #endif 

View Code

双向链表的实现文件(double_link.c)

《队列的图文解析 和 对应3种语言的实现(C/C++/Java)》
《队列的图文解析 和 对应3种语言的实现(C/C++/Java)》

  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)

《队列的图文解析 和 对应3种语言的实现(C/C++/Java)》
《队列的图文解析 和 对应3种语言的实现(C/C++/Java)》

 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)

《队列的图文解析 和 对应3种语言的实现(C/C++/Java)》
《队列的图文解析 和 对应3种语言的实现(C/C++/Java)》

 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 #endif 

View Code

双向链表的实现文件(double_link.c)

《队列的图文解析 和 对应3种语言的实现(C/C++/Java)》
《队列的图文解析 和 对应3种语言的实现(C/C++/Java)》

  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)

《队列的图文解析 和 对应3种语言的实现(C/C++/Java)》
《队列的图文解析 和 对应3种语言的实现(C/C++/Java)》

  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++实现

C++的STL中本身就包含了list类,基本上该list类就能满足我们的需求,所以很少需要我们自己来实现。本部分介绍2种C++实现。
1. C++实现一:数组实现的队列,能存储任意类型的数据。
2. C++实现二:C++的 STL 中自带的”队列”(list)的示例。

 

1. C++实现一:数组实现的队列,能存储任意类型的数据

实现代码
队列的实现文件(ArrayQueue.h)

《队列的图文解析 和 对应3种语言的实现(C/C++/Java)》
《队列的图文解析 和 对应3种语言的实现(C/C++/Java)》

 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)

《队列的图文解析 和 对应3种语言的实现(C/C++/Java)》
《队列的图文解析 和 对应3种语言的实现(C/C++/Java)》

 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)

《队列的图文解析 和 对应3种语言的实现(C/C++/Java)》
《队列的图文解析 和 对应3种语言的实现(C/C++/Java)》

 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

 

队列的Java实现

和C++一样,JDK包Queue中的也提供了”队列”的实现。JDK中的Queue接口就是”队列”,它的实现类也都是队列,用的最多的是LinkedList。本部分介绍给出2种Java实现
1. Java实现一:数组实现的队列,能存储任意类型的数据。
2. Java实现二:Java的 Collection集合 中自带的”队列”(LinkedList)的示例。

 

1. Java实现一:数组实现的队列,能存储任意类型的数据

实现代码(ArrayQueue.java)

《队列的图文解析 和 对应3种语言的实现(C/C++/Java)》
《队列的图文解析 和 对应3种语言的实现(C/C++/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)

《队列的图文解析 和 对应3种语言的实现(C/C++/Java)》
《队列的图文解析 和 对应3种语言的实现(C/C++/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

 

    原文作者:算法小白
    原文地址: https://www.cnblogs.com/skywang12345/p/3562279.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞