線性結構:有且只有一個根節點,且每個節點最多有一個直接前驅和一個直接后繼的非空數據結構
非線性結構:不滿足線性結構的數據結構
隊列
隊列一般分為兩類:鏈式隊列和順序隊列
鏈式隊列---鏈式隊列即用鏈表實現的隊列
順序隊列---順序隊列是用數組實現的隊列,順序隊列通常必須是循環隊列
1、基本概念:
隊列是指允許在一端進行插入,在另一端進行刪除的線性表,又稱“先進先出”的線性表
隊列是一種特殊的線性結構,它只允許在隊列的首部(head)進行刪除操作,這稱為出隊
隊尾:允許插入的一端,用尾指針指向隊尾元素的后一位置
隊首:允許刪除的一端,用頭指針指向頭元素
循環隊列(順序隊列)的實現:
1 #include <stdio.h> 2 3 #define LENGTH 11 /*定義數組最大長度 */ 4 #define OUT 1 /* 出隊 */ 5 #define GET 2 /* 入隊 */ 6 struct queue 7 { 8 int data[LENGTH]; 9 int head; /* 隊首 */ 10 int tail; /* 隊尾 */ 11 }; 12 /* 循環隊列的實現 */ 13 main() 14 { 15 struct queue q; 16 int i; 17 int kk = 0; 18 /* 初始化隊列 */ 19 q.head = q.tail = 0; /*隊首隊尾初始化 */ 20 /* 依次插入10個數 */ 21 for (i = 0; i < LENGTH - 1; i++) 22 { 23 scanf_s("%d", &q.data[q.tail]); 24 q.tail = (q.tail + 1) % LENGTH; 25 } 26 while (1) 27 { 28 if (q.head == q.tail) 29 { 30 printf("隊列已空"); 31 break; 32 } 33 printf("出隊:1\n入隊:2\n"); 34 scanf_s("%d", &kk); 35 if (kk == OUT) 36 { 37 38 q.head = (q.head + 1) % LENGTH; 39 } 40 else if (kk == GET) 41 { 42 if (q.head == (q.tail + 1) % LENGTH) 43 { 44 printf("隊列已滿"); 45 break; 46 } 47 printf("輸入入隊元素:\n"); 48 scanf_s("%d", &q.data[q.tail]); 49 q.tail = (q.tail + 1) % LENGTH; 50 } 51 52 if (q.tail != q.head) 53 { 54 printf("隊列中剩余元素:"); 55 for (i = q.head; ;) 56 { 57 printf("%d ", q.data[i]); 58 i = (i + 1) % LENGTH; 59 if(i == q.tail) 60 { 61 putchar('\n'); 62 break; 63 } 64 } 65 } 66 } 67 68 69 70 return 0; 71 }
2、為什么順序隊列通常必須是循環隊列
循環隊列是針對順序隊列中最大內存空間有限的一種解決方法,當隊列(數組)不可再插入新元素但隊列的實際可用空間並未占滿的問題的一種合理的解決方案
3、與普通順序隊列的區別
普通順序隊列在插入新元素(入隊)時為q.tail++,刪除舊元素(出隊)時為q.head++(q.tail和q.head都為int型,但為了描述方便這里說成指針),在出隊后再想插入新元素且此時q.tail在數組的末尾即最后一位就會出現實際可用空間並未占滿但無法插入新元素的問題,強行插入會造成數組越界,也不宜繼續擴大數組空間,造成了空間上的浪費
循環隊列的核心在於隊頭指針和隊尾指針的增加方式
q.head = (q.head + 1) % LENGTH;
q.tail = (q.tail + 1) % LENGTH;
這樣實現了臆想上存儲空間的彎曲效果,也解決了空間上的浪費(建議在紙上模擬循環隊列數組的出隊入隊操作,以理解上面兩行代碼)
值得注意的是
q.head指向的是隊首元素
q.tail指向的是隊尾元素的后一位,浪費了一位空間,例如數組q.data[11]插入10個元素后q.tail指向的是q.data[10]即q.tail = 10;
4、循環隊列的新問題
當隊列為空時q.head = q.tail,當隊列為滿時也有q.head = q.tail造成了判斷隊列是空還是滿的二義性
解決方法: 1.增加一個參數,使刪除元素為1,插入元素為0
2.增加一個參數,記錄隊列的元素個數即長度
3.空出一個單元,令if(q.head == (q.tail + 1) % LENGTH)為隊列為滿的條件,以此解決二義性
5、注意
循環隊列的頭指針和尾指針的減少或增加方式
隊列為滿或空的判定條件
循環隊列參考鏈接:
https://www.cnblogs.com/chenliyang/p/6554141.html 該篇比較詳細
https://blog.csdn.net/smile_zhangw/article/details/80894159
(編譯器:Microsoft Visual C++ 2010 Express)