概要
本章和介绍"栈"时的流程一样,先对队列进行介绍,然后分别给出队列的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 ", tmp); 94 95 // 只将“队列开头的元素”赋值给tmp,不删除该元素. 96 tmp = front(); 97 printf("tmp=%d ", tmp); 98 99 add(40); 100 101 // 打印队列 102 printf("is_empty()=%d ", is_empty()); 103 printf("size()=%d ", size()); 104 while (!is_empty()) 105 { 106 printf("%d ", pop()); 107 } 108 109 // 销毁队列 110 destroy_array_queue(); 111 }
运行结果:
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 ", tmp); 115 116 // 只将“队列开头的元素”赋值给tmp,不删除该元素. 117 tmp = front(); 118 printf("tmp=%d ", tmp); 119 120 add(40); 121 122 printf("is_empty()=%d ", is_empty()); 123 printf("size()=%d ", size()); 124 while (!is_empty()) 125 { 126 printf("%d ", pop()); 127 } 128 129 // 销毁队列 130 destroy_single_link(); 131 }
代码说明:"运行结果" 以及 "主函数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
双向链表的实现文件(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! "); 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! ", __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! ", __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! ", __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! ", __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! ", __func__); 253 return ; 254 } 255 256 printf("%s dlink size()=%d ", __func__, count); 257 node *pnode=phead->next; 258 while(pnode != phead) 259 { 260 printf("%d ", pnode->value); 261 pnode = pnode->next; 262 } 263 }
双向链表的测试程序(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 ", tmp); 70 71 // 只将“队列开头的元素”赋值给tmp,不删除该元素. 72 tmp = front(); 73 printf("tmp=%d ", tmp); 74 75 add(40); 76 77 printf("is_empty()=%d ", is_empty()); 78 printf("size()=%d ", size()); 79 while (!is_empty()) 80 { 81 printf("%d ", pop()); 82 } 83 84 // 销毁队列 85 destroy_dlink_queue(); 86 }
代码说明:"运行结果" 以及 "主函数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
双向链表的实现文件(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! "); 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! ", __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! ", __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! ", __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! ", __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 }
双向链表的测试程序(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 ", 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 ", is_empty()); 104 printf("size()=%d ", size()); 105 // 打印队列中的所有元素 106 while (!is_empty()) 107 { 108 pval = pop(); 109 print_stu(pval) ; 110 } 111 112 // 销毁队列 113 destroy_dlink_queue(); 114 }
运行结果:
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
队列的测试程序(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 }
运行结果:
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 }
运行结果:
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 ", tmp); 58 59 // 只将“栈顶”赋值给tmp,不删除该元素. 60 tmp = astack.front(); 61 System.out.printf("tmp=%d ", tmp); 62 63 astack.add(40); 64 65 System.out.printf("isEmpty()=%b ", astack.isEmpty()); 66 System.out.printf("size()=%d ", astack.size()); 67 while (!astack.isEmpty()) { 68 System.out.printf("size()=%d ", astack.pop()); 69 } 70 } 71 }
运行结果:
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 ", slist.isEmpty()); 61 System.out.printf("size()=%d ", slist.size()); 62 while(!slist.isEmpty()) { 63 System.out.printf("%d ", slist.get()); 64 } 65 } 66 }
运行结果:
tmp=10 tmp=20 isEmpty()=false size()=3 tmp=20 tmp=30 tmp=40