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 */
运行截图: