队列:先进先出的线性表,它只允许在一端(队尾)进行插入操作,在另一端(队首)进行删除操作。与栈的插入和删除都在栈顶进行不同。
这里只说队列的链式存储。国际惯例,先上源码
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<malloc.h> 4 5 //定义队列 6 typedef struct node{ 7 int data; 8 struct node *next; 9 }Queue; 10 //定义对手指针和队尾指针 11 typedef struct pointer{ 12 Queue *front;//队首指针,对手指针不存放队列元素 13 Queue *rear;//队尾指针,存放队尾的数据元素 14 }Qpointer; 15 16 //队列初始化 17 void QueueInit(Qpointer *qp) 18 { 19 Queue *que; 20 que=(Queue*)malloc(sizeof(Queue)); 21 que->next=NULL; 22 //队首和队尾指向同一个内存空间,指针域为NULL 23 qp->front=que; 24 qp->rear=que; 25 } 26 27 //判断队列是否为空:为空返回1,不为空返回0 28 int IsEmpty(Qpointer *qp) 29 { 30 //判断方法:对手指针和队尾指针是否相同 31 if(qp->front==qp->rear) 32 { 33 return 1; 34 } 35 return 0; 36 } 37 38 //插入数据元素:插入成功返回1,失败返回0 39 int QueuePush(Qpointer *qp,int element) 40 { 41 Queue *que; 42 que=(Queue*)malloc(sizeof(Queue)); 43 if(que==NULL) 44 { 45 return 0; 46 } 47 que->data=element; 48 que->next=NULL; 49 qp->rear->next=que;//将节点插入队列尾 50 qp->rear=que;//调整队尾指针 51 return 0; 52 } 53 54 //删除数据元素:删除成功返回1,失败返回0 55 int QueuePop(Qpointer *qp,int *element) 56 { 57 Queue *que; 58 if(IsEmpty(qp)) 59 { 60 return 0; 61 } 62 que=qp->front->next;//que指向队列头结点的下一个节点,即真正的队首 63 *element=que->data;//将要出队列的元素 64 qp->front->next=que->next; 65 //判断队列是否就只剩下一个元素 66 if(qp->rear==que) 67 { 68 qp->rear=qp->front; 69 } 70 free(que); 71 return 1; 72 } 73 74 int main() 75 { 76 Qpointer *qp; 77 int x; 78 //初始化队列 79 qp=(Qpointer*)malloc(sizeof(Qpointer)); 80 QueueInit(qp); 81 printf("input positive integers:\n"); 82 scanf("%d",&x); 83 while(x>0) 84 { 85 QueuePush(qp,x); 86 scanf("%d",&x); 87 } 88 //输出队列:队首->队尾 89 Queue *p=qp->front->next; 90 if(p==NULL) 91 return 0; 92 printf("queue element:\n"); 93 while(p) 94 { 95 printf("%d ",p->data); 96 p=p->next; 97 } 98 printf("\n"); 99 //删除队列 100 printf("delete queue:\n"); 101 while(QueuePop(qp,&x)) 102 { 103 printf("%d ",x); 104 } 105 printf("\n"); 106 //释放内存空间 107 p=qp->front; 108 free(p); 109 free(qp); 110 111 return 0; 112 }
1.队列定义:这里除了定义队列中节点的数据结构,还专门定义了队首和队尾,方便对队列操作,这样一来,队列的操作就只需要对pointer结构体中的对手指真和队尾指针进行。
2.判断是否为空
当队首指针和队尾指针只想同一块地址时,队列为空,队列为空就是说队列中没有数据元素。注意队首front只是队列的头结点,并不代表队列的实际队首,在队列不为空时,队列的实际队首应该是头结点的下一个节点。
3.插入数据元素
插入在队尾进行,插入后,新插入的节点就成为了队尾。
4.删除数据元素
删除在队首进行,需要注意的是,当实际的队首也是队尾时,删除队列中的一个数据后队列就成为了空队列(rear=front)。最后不要忘了将删除的数据的内存空间释放掉。
5.注意点
最后释放内存时,一定要先释放掉pointer中的队首指针和队尾指针指向的内存空间,再释放掉pointer结构体指向的内存空间。
使用GDB调试,可知pointer结构体的内存模型如下:
这时初始化队列后的情况,并未插入任何数据。pointer结构体指针变量qp指向0x804b008,因为qp中有两个指针变量,所以占8个字节的内存空间,分别存放front(指向0x804b018)指针变量和rear(指向0x804b018)指针变量