队列的链式存储(C语言实现)

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 
  4 #define OK 1
  5 #define ERR 2
  6 #define TRUE 1
  7 #define FALSE 0
  8 
  9 typedef int status; //定义函数返回的状态,OK & ERR
 10 typedef char datatype; //定义队列中每个元素的数据类型,这里暂定为字符型
 11 
 12 typedef struct LinkQueue_anon{
 13     datatype data; //数据区
 14     struct LinkQueue_anon * next; //指针区
 15 } LinkQueue;
 16 typedef struct {
 17     LinkQueue * front, * rear;
 18     /*
 19     创建队列的游标,保存着队列的头尾指针所指向的结点
 20     front指向队列的第一个结点(队头),rear指向队列的最后一个结点(队尾)
 21     规定:
 22         当front=rear=NULL时,表示队列为空
 23         当front=rear!=NULL时,表示队列只有一个元素
 24     */
 25 }LinkQueueCursor;
 26 
 27 /* 函数原型,队列的基本操作,与栈相同 */
 28 LinkQueueCursor *createLinkQueue(datatype first_node_value);
 29 status isEmpty(LinkQueueCursor *L);
 30 void clear(LinkQueueCursor *L);
 31 datatype getTop(LinkQueueCursor *L);
 32 int getLength(LinkQueueCursor *L);
 33 status push(LinkQueueCursor *L, datatype node_to_push);
 34 datatype pop(LinkQueueCursor *L);
 35 void showQueue(LinkQueueCursor *L);
 36 
 37 int main(){
 38     /* 测试 */
 39     LinkQueueCursor * mycursor;
 40     mycursor=createLinkQueue('1'); //创建一个游标,同时入队一个元素,其值为'1'
 41     printf("isEmpty = %d\n",isEmpty(mycursor));
 42     printf("Length = %d\n",getLength(mycursor));
 43     push(mycursor,'a');
 44     push(mycursor,'b');
 45     push(mycursor,'c');
 46     push(mycursor,'d');
 47     printf("isEmpty = %d\n",isEmpty(mycursor));
 48     printf("Length = %d\n",getLength(mycursor));
 49     showQueue(mycursor);
 50     putchar('\n');
 51     printf("pop = %c\n",pop(mycursor));
 52     printf("pop = %c\n",pop(mycursor));
 53     printf("getTop = %c\n",getTop(mycursor));
 54     printf("isEmpty = %d\n",isEmpty(mycursor));
 55     printf("Length = %d\n",getLength(mycursor));
 56     showQueue(mycursor);
 57     putchar('\n');
 58     clear(mycursor);
 59     printf("isEmpty = %d\n",isEmpty(mycursor));
 60     printf("Length = %d\n",getLength(mycursor));
 61 
 62     return 0;
 63 }
 64 
 65 LinkQueueCursor *createLinkQueue(datatype first_node_value){
 66     LinkQueueCursor *tmp_cur;
 67     LinkQueue *tmp;
 68     tmp_cur=malloc(sizeof(LinkQueueCursor)); //void*类型指针能自动转为其他类型的指针
 69     tmp=malloc(sizeof(LinkQueue));
 70     tmp_cur->front=tmp_cur->rear=tmp; //初始化游标
 71     tmp->data=first_node_value; //初始化数据区
 72     tmp->next=NULL; //初始化指针区
 73     return tmp_cur;
 74 }
 75 status isEmpty(LinkQueueCursor *L){
 76     if (L->front==L->rear && L->front==NULL)
 77         return TRUE;
 78     else
 79         return FALSE;
 80 }
 81 void clear(LinkQueueCursor *L){
 82     LinkQueue * p,* q;
 83     if (isEmpty(L)) return; //空队列,不需要clear,所以直接返回
 84     if (L->front==L->rear && L->front!=NULL){ //只有一个元素的队列,front和rear都指向这个元素
 85         free(L->front);
 86         L->front=L->rear=NULL; //把队列设为空
 87         return;
 88     }
 89     /* 当队列的元素大于1时 */
 90     p=L->front; //p指向当前要被删除的结点
 91     while (p){
 92         //当p不为NULL继续循环
 93         q=p->next; //q指向p的下一个结点
 94         free(p);
 95         p=q; //交换
 96     }
 97     L->front=L->rear=NULL; //把队列设为空
 98 
 99 }
100 datatype getTop(LinkQueueCursor *L){
101     return L->front->data; //直接返回队头的数据即可
102 }
103 int getLength(LinkQueueCursor *L){
104     int i=0;
105     LinkQueue * p;
106     if (isEmpty(L)) return 0; //空队列,返回0
107     if (L->front==L->rear && L->front!=NULL) return 1; //规定:front=rear,说明队列只有一个元素
108     /* 队列的长度大于1时 */
109     p=L->front;
110     while (p!=L->rear){ //还没到rear(队尾)则继续循环
111         i++; p=p->next;
112     }
113     return i+1;
114     /*
115     上面的【队列的长度大于1时】还能用下面的等价代码代替
116     p=L->front;
117     while (p){ //p不为NULL则继续循环,因为rear(队尾)结点的next(指针区)一定是NULL
118         i++; p=p->next;
119     }
120     return i;
121     */
122 }
123 status push(LinkQueueCursor *L, datatype node_to_push){
124     //node_to_insert表示想要在队尾处入队的元素
125     LinkQueue * s=malloc(sizeof(LinkQueue));
126     s->data=node_to_push; //初始化新入队的元素
127     s->next=NULL;
128     if (isEmpty(L)==TRUE){
129         //插入到空队列
130         L->front=L->rear=s; //入队,当队列只有一个元素时,规定front和rear都指向这个元素
131     }else{
132         //插入到已存在元素的队列
133         L->rear->next=s; //入队,将新元素附在rear指向的结点的后面
134         L->rear=s; //rear后移,即将它指向新元素
135     }
136     return OK;
137 }
138 datatype pop(LinkQueueCursor *L){
139     //出队,即将队头删除
140     datatype v;
141     LinkQueue * s;
142     if (isEmpty(L)) return (datatype)ERR; //空队列
143     if (L->front==L->rear && L->front!=NULL){ //队列只有一个元素
144         v=L->front->data; //把这个元素的值赋值给临时变量
145         free(L->front); //删除这个元素
146         L->front=L->rear=NULL; //把队列设置为空
147     }else{
148         v=L->front->data; //将要删除的元素的值先赋值给临时变量
149         s=L->front; //将要删除的元素先赋值给临时变量
150         L->front=L->front->next; //将游标所保存的front后移到下个结点(元素)
151         free(s); //删除原来的头结点(元素)
152     }
153     return v; //返回出队结点(元素)的值
154 }
155 void showQueue(LinkQueueCursor *L){
156     int i;
157     int total=getLength(L);
158     LinkQueue * p;
159     p=L->front;
160     for (i=0; i<total; i++){
161         printf("%c\t",p->data); p=p->next;
162     }
163 }
164 /*
165     队列的定义:只允许在一端进行插入,另一端进行删除的线性表,也是一种操作受限的线性表
166     一般,把允许插入的一端叫做队尾,允许删除的一端叫做队头
167     不含任何元素的队列就是空队
168     所以,队列又称先进先出(First in First out)的线性表
169     队列的链式存储其实就是线性表中的单链表,只不过它只能尾进头出
170 */
171 /* 环境: Code::Blocks with GCC 5.1 */

运行截图:

队列的链式存储(C语言实现)

 

上一篇:【赵强老师】如何在MongoDB中使用游标查询数据


下一篇:游标