1. 程式人生 > 實用技巧 >資料結構與演算法——佇列(鏈式儲存)

資料結構與演算法——佇列(鏈式儲存)

佇列的鏈式儲存結構,其實就是線性表的單鏈表,只不過它只是尾進頭出而已,我們把它簡稱為鏈佇列。為了操作上的方便,我們將隊頭指標指向鏈佇列的頭結點,而隊尾指標指向終端節點。

 1 typedef int DataType;            //佇列中元素型別
 2 typedef struct _QNode            //結點結構
 3 { 
 4     DataType data; 
 5     struct _QNode* next;
 6 }QNode; 
 7 
 8 typedef QNode* QueuePtr;        //結點結構指標
 9 
10 typedef struct
Queue 11 { 12 int length; //佇列的長度 13 QueuePtr front; //隊頭指標 14 QueuePtr rear; //隊尾指標 15 }LinkQueue;

鏈式佇列操作圖示

空佇列時,front 和 rear 都指向空。

完整實現程式碼:

  1 #include <stdio.h>
  2 #include <assert.h>
  3 #include <Windows.h>
  4 #include <iostream> 
  5 #include <iomanip> 
  6
7 using namespace std; 8 9 #define MaxSize 5 //佇列的最大容量 10 typedef int DataType; //佇列中元素型別 11 12 typedef struct _QNode //結點結構 13 { 14 DataType data; 15 struct _QNode* next; 16 }QNode; 17 18 typedef QNode* QueuePtr; //結點結構指標 19 20 typedef struct Queue 21 { 22 int
length; //佇列的長度 23 QueuePtr front; //隊頭指標 24 QueuePtr rear; //隊尾指標 25 }LinkQueue; 26 27 //佇列初始化,將佇列初始化為空佇列 28 void InitQueue(LinkQueue* LQ) 29 { 30 if (!LQ) return; 31 LQ->length = 0; 32 LQ->front = LQ->rear = NULL; //把對頭和隊尾指標同時置0 33 } 34 35 //判斷佇列為空 36 int IsEmpty(LinkQueue* LQ) 37 { 38 if (!LQ) return 0; if (LQ->front == NULL) 39 { 40 return 1; 41 } return 0; 42 } 43 44 //判斷佇列是否為滿 45 int IsFull(LinkQueue* LQ) 46 { 47 if (!LQ) return 0; 48 if (LQ->length == MaxSize) 49 { 50 return 1; 51 } return 0; 52 } 53 54 //入隊,將元素data插入到佇列LQ中 55 int EnterQueue(LinkQueue* LQ, DataType data) 56 { 57 if (!LQ) return 0; 58 if (IsFull(LQ)) 59 { 60 cout << "無法插入元素 " << data << ", 佇列已滿!" << endl; 61 return 0; 62 } 63 QNode* qNode = new QNode; qNode->data = data; qNode->next = NULL; 64 if (IsEmpty(LQ)) //空佇列 65 { 66 LQ->front = LQ->rear = qNode; 67 } 68 else 69 { 70 LQ->rear->next = qNode; //在隊尾插入節點qNode 71 LQ->rear = qNode; //隊尾指向新插入的節點 72 } 73 LQ->length++; 74 return 1; 75 } 76 77 //出隊,將佇列中隊頭的元素出隊,其後的第一個元素成為新的隊首 78 int DeleteQueue(LinkQueue* LQ, DataType* data) 79 { 80 QNode* tmp = NULL; 81 if (!LQ || IsEmpty(LQ)) 82 { 83 cout << "佇列為空!" << endl; 84 return 0; 85 } 86 if (!data) return 0; 87 tmp = LQ->front; 88 LQ->front = tmp->next; 89 if (!LQ->front) LQ->rear = NULL; //如果對頭出列後不存在其他元素,則rear節點也要置空 90 * data = tmp->data; 91 LQ->length--; 92 delete tmp; 93 return 1; 94 } 95 //列印佇列中的各元素 96 void PrintQueue(LinkQueue* LQ) 97 { 98 QueuePtr tmp; 99 if (!LQ) return; 100 if (LQ->front == NULL) 101 { 102 cout << "佇列為空!"; 103 return; 104 } 105 tmp = LQ->front; 106 while (tmp) 107 { 108 cout << setw(4) << tmp->data; 109 tmp = tmp->next; 110 } 111 cout << endl; 112 } 113 114 //獲取隊首元素,不出隊 115 int GetHead(LinkQueue* LQ, DataType* data) 116 { 117 if (!LQ || IsEmpty(LQ)) 118 { 119 cout << "佇列為空!" << endl; 120 return 0; 121 } if (!data) return 0; 122 *data = LQ->front->data; 123 return 1; 124 } 125 126 //清空佇列 127 void ClearQueue(LinkQueue* LQ) 128 { 129 if (!LQ) return; 130 while (LQ->front) 131 { 132 QueuePtr tmp = LQ->front->next; 133 delete LQ->front; 134 LQ->front = tmp; 135 } 136 LQ->front = LQ->rear = NULL; 137 LQ->length = 0; 138 } 139 140 //獲取佇列中元素的個數 141 int getLength(LinkQueue* LQ) 142 { 143 if (!LQ) return 0; 144 return LQ->length; 145 } 146 147 int main() 148 { 149 LinkQueue* LQ = new LinkQueue; 150 DataType data = -1; 151 152 //初始化佇列 153 InitQueue(LQ); 154 155 //入隊 156 for (int i = 0; i < 7; i++) 157 { 158 EnterQueue(LQ, i); 159 } 160 161 //列印佇列中的元素 162 printf("佇列中的元素(總共%d 個):", getLength(LQ)); 163 PrintQueue(LQ); 164 cout << endl; 165 166 //出隊 167 for(int i=0; i<10; i++) 168 { 169 if(DeleteQueue(LQ, &data)) 170 { 171 cout<<"出隊的元素是:"<<data<<endl; 172 } 173 else 174 { 175 cout << "出隊失敗!" << endl; 176 } 177 } 178 179 //列印佇列中的元素 180 printf("出隊一個元素後,佇列中剩下的元素[%d]:", getLength(LQ)); 181 PrintQueue(LQ); 182 cout << endl; 183 ClearQueue(LQ); 184 cout << "清空佇列!\n"; 185 PrintQueue(LQ); 186 //清理資源 delete LQ; 187 system("pause"); 188 189 return 0; 190 }

================================================================================================================