數據結構與演算法筆記 cp2-1:線性表
- 2019 年 11 月 7 日
- 筆記
線性表
1.1 定義:
List,由零個或多個數據特性相同的元素構成的有限序列。個數 n 稱為線性表的長度,n=0 的時候稱為空表。比如說,十二星座就是一個線性表,它的「第一個」和「最後一個」元素都是唯一的,並且中間的元素均只有一個前驅、一個後繼。
1.2 抽象數據類型
ADT List{ Data:....... Operation: InitList(&L): 初始化,建立一個空的線性表L ClearList(&L): 清空線性表L GetElem(L,i,&e): 將L中第i個位置元素值返回給e LocateElem(L,e): 在L中查找與e相等的元素 ListInsert(&L,i,e): 在L中第i個位置插入新元素e ListDelete(&L,i,&e): 刪除L中第i個位置元素,並用e返回其值 ListLength(L): 返回L長度 } ADT List線性表的順序存儲結構 / 順序表
2.1 定義:
指的是用一段地址連續的存儲單元依次存儲線性表的數據元素。

各個元素的地址之間構成等差數列,因此,知道了某一個元素的地址,就可以隨時推導出其它元素的地址,也就是說不管取出還是存入哪一個元素,花費的時間都一樣,是一個常數(O(1)),這種特性的存儲結構就叫隨機存取結構。
一維數組可以實現線性表的順序存儲結構,不過要注意數組下標從0開始,而說線性表的時候說的是位序,是從1開始的。
2.2 基本操作
(1) 初始化:
首先定義線性表順序存儲結構:
typedef struct Table{ int * head;//聲明了一個名為head的長度不確定的數組,也叫「動態數組」 int length;//記錄當前順序表的長度 int size;//記錄順序表分配的存儲容量 }table;第一個操作是初始化,包括:給head申請足夠大小的物理空間;給size和length賦初值:
#define Size 5 //對Size進行宏定義,表示順序表申請空間的大小 table initTable(){ table t; t.head=(int*)malloc(Size*sizeof(int));//構造一個空的順序表,動態申請存儲空間 if (!t.head) //如果申請失敗,作出提示並直接退出程式 { printf("初始化失敗"); exit(0); } t.length=0;//空表的長度初始化為0 t.size=Size;//空表的初始存儲空間為Size return t; }(2) 取值: 找某一個位序的元素,只需要判斷位序的合法性,之後返回數組[位序-1]即可。
(3) 查找/修改: 遍曆數組元素,與目標元素比較,相等則返回。如果要修改,重新賦值即可。
(4) 刪除: 找到目標元素,讓後續元素整體前移一個位置,之後長度減一即可。
table delTable(table t,int add){ if (add>t.length || add<1) { printf("被刪除元素的位置有誤"); exit(0); } //刪除操作 for (int i=add; i<t.length; i++) { t.head[i-1]=t.head[i]; } t.length--; return t; }比如說要刪除5個元素中的第三個,那麼 add 就是 3,而 t.head[3] 就是第四個元素,從這個元素開始依次向前移動並覆蓋前面的元素。
(5) 插入: 找到目標位置,將該位置對應元素以及後續元素整體後移一個位置,之後長度加一即可。
//插入函數,其中,elem為插入的元素,add為插入到順序表的位置 table addTable(table t,int elem,int add) { //判斷插入本身是否存在問題 if (add>t.length+1||add<1) { printf("插入位置有問題"); return t; } //線性表長度等於數組長度,沒有多餘空間容納新插入的元素,此時需要申請 if (t.length==t.size) { t.head=(int *)realloc(t.head, (t.size+1)*sizeof(int)); if (!t.head) { printf("存儲分配失敗"); return t; } t.size+=1; } for (int i=t.length-1; i>=add-1; i--) { t.head[i+1]=t.head[i]; } t.head[add-1]=elem; t.length++; return t; }
- 首先要注意範圍的判斷,add 作為目標位置,至少也得等於1,此時是插在最前面;同時,add 可以等於 length+1,此時是插在最後面,但不能比 length+1 更大了,否則會出現空隙。
- 接著要注意是從後往前遍歷的,因為如果是從前往後的話就會發生覆蓋。
- 可以不做「目標位置是否在表尾」的判斷,這樣會直接繞過for循環,執行賦值。
這裡可以發現,線性表的插入和刪除元素操作往往需要移動大量的元素。
