隊列:先進先出的線性表,它只允許在一端(隊尾)進行插入操作,在另一端(隊首)進行刪除操作。與棧的插入和刪除都在棧頂進行不同。
這里只說隊列的鏈式存儲。國際慣例,先上源碼
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)指針變量