引言
数据结构中的队列模型和我们日常生活中的排队情况是一致的,排队买票,窗口一端叫队头,末尾进队叫队尾; 最先在前面买票的先离开,最早进入队列的元素最早离开。 所以队列又称作FIFO表(First in First out)。
队列(Queue)是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。
进行插入操作的端称为队尾,进行删除操作的端称为队头。
二、队列定义及实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| #ifndef _QUEUE_H_ #define _QUEUE_H_
#include "dlist.h"
typedef struct Queue { Dlist *dlist; //封装我们已经实现的链表 }Queue;
//1.初始化 Queue *init_queue(void); //2.销毁 void destroy_queue(Queue **queue); //3.入队 void in_queue(Queue *queue, void *value);/*入队返回值:空*/ //4.出队 Boolean out_queue(Queue *queue); //5.得到队首元素 Boolean get_front_queue(Queue *queue, void **value); //6.判断队列是否为空 Boolean is_queue_empty(Queue *queue); //7.得到队列元素个数 int get_queue_count(Queue *queue); #endif
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| #ifndef _DLIST_H_ #define _DLIST_H_
#define TRUE (1) #define FALSE (0) #define ZERO (0) #define ONLY_ONE (1) typedef unsigned char Boolean ; typedef void (*Print_func)(void *value);
void print_int(void *data);
typedef struct Dlist_node{ struct Dlist_node *prev; struct Dlist_node *next; //指向后一个节点 void *data; }Dlist_node;
//通用链表控制信息 typedef struct Dlist{ struct Dlist_node *head; //指向头结点 struct Dlist_node *tail; int count;
//这是一个指向某个需要被释放的数据域的函数指针 void (*free)(void *ptr); //比较节点数据域 Boolean (*match)(void *value1, void *value2); //拷贝节点数据域 void *(*copy_node)(void *value); }Dlist;
//双端链表的初始化 Dlist *init_dlist(void); //双端链表的销毁 void destroy_dlist(Dlist **dlist);//二重指针 //头部插入 Boolean push_front(Dlist *dlist, void *data); //尾部插入 Boolean push_back(Dlist *dlist, void *data); //头部删除 Boolean pop_front(Dlist *dlist); //尾部删除 Boolean pop_back(Dlist *dlist); //插入到当前节点前 Boolean insert_prev(Dlist *dlist, Dlist_node *node, void *value); //插入到当前节点后 Boolean insert_next(Dlist *dlist, Dlist_node *node, void *value); //删除某个节点 Boolean remove_dlist_node(Dlist *dlist, Dlist_node *node); //显示双端链表信息 void show_dlist(Dlist *dlist, Print_func print); //得到第一个节点数据域 Boolean get_front(Dlist *dlist, void **value); //得到最后一个节点数据域 Boolean get_tail(Dlist *dlist, void **value); //得到链表节点数量 int get_dlist_count(Dlist *dlist);
#endif
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
| #include <stdio.h> #include "queue.h" #include "tools.h"
//1.初始化 Queue *init_queue(void) { Queue *queue = (Queue *)Malloc(sizeof(Queue)); queue->dlist = init_dlist();
return queue; }
//2.销毁 void destroy_queue(Queue **queue) { if(queue == NULL || *queue == NULL) { return; } destroy_dlist( &((*queue)->dlist) ); free(*queue); *queue = NULL; }
//3.入队 void in_queue(Queue *queue, void *value)/*入队返回值:空*/ { if(queue == NULL || value == NULL) { return ; } push_back(queue->dlist, value); //后插法 }
//4.出队 Boolean out_queue(Queue *queue) { if(queue == NULL || is_queue_empty(queue)) { return FALSE; } return pop_front(queue->dlist); //前删 }
//5.得到队首元素 Boolean get_front_queue(Queue *queue, void **value) { if(queue == NULL || is_queue_empty(queue)) { return FALSE; } if(value != NULL){ return get_front(queue->dlist, value); } }
//6.判断队列是否为空 Boolean is_queue_empty(Queue *queue) { return get_queue_count(queue) == ZERO; }
//7.得到队列元素个数 int get_queue_count(Queue *queue) { if(queue == NULL) { return -1; } return get_dlist_count(queue->dlist); }
|
由于我们封装的链表操作提供了接口,我们可以发现,再用我们已经实现过的代码去完成新的结构新的操作就会变得简单的多。
由此可见,代码的冗余性低,并实现通用化对学习工作都会有很大的用处。
三、代码功能测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| #include <stdio.h> #include "queue.h"
int main(int argc, char **argv) { int i = 0; int a[]={1,2,3,4,5}; int *value = NULL; int length = sizeof(a)/sizeof(a[0]);
Queue *queue = NULL; queue = init_queue(); for(i=0; i< length;++i) { in_queue(queue, &a[i]); }
Dlist_node *node = queue->dlist->head; for(i=0; i< length ;++i) { print_int(node->data); node = node ->next; } printf("\n"); printf("Top:"); get_front_queue(queue, (void **)&value); printf("%d ",*value); printf("\n");
printf("the length:\n"); printf("%d \n",get_queue_count(queue));
for(i = 0; i < length ; ++i) { get_front_queue(queue,(void **)&value); out_queue(queue); printf("%d ",*value); } printf("\n"); destroy_queue(&queue); return 0; }
|
1 2 3 4 5 6 7 8 9 10 11 12
| root@aemonair:# cc.sh *.c Compiling ... -e CC dlist.c main.c queue.c tools.c -g -lpthread -e Completed . -e Sat Jun 18 10:33:45 CST 2016
root@aemonair:# ./dlist 1 2 3 4 5 Top:1 the length: 5 1 2 3 4 5
|
总结
我们这次还只是很简单的实现了最简单的顺序队列,而且只是仅仅对我们已经实现的链表功能进行再次加工制造,那么,有了这样的通用思想后,我们需要对自己的代码进行模块化,同时不能只是简单的利用这些代码,要从深处底层了解,才能更好的进行使用。
对于编程功底的联系以及使用模块化代码并无矛盾,我们一方面要加强代码能力,也要能够利用我们已写过的简单代码,来有更多时间完成更深更有难度的功能。