隊列的圖文解析 和 對應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. 隊列的示意圖

隊列中有10,20,30共3個數據。

 

2. 出隊列

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

 

3. 入隊列

入隊列前:隊首是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)

  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 #endif 
View 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 #endif 
View 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++實現

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

 

隊列的Java實現

和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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM