大話資料結構筆記_線性表
阿新 • • 發佈:2018-11-07
線性表的定義 :
簡而言之 : 0 個 或 多個元素(型別相同)的有限序列( 有順序 ) , 第一個元素無前驅 , 最後一個元素無後繼 , 其他元素 與有唯一的前驅 和 唯一的後繼
數學語言定義 : 若將線性表記為 ( a1 , a2 , ..... , ai - 1 , ai , ai+1 , ... , an) , 則表中 ai-1 領先於 ai , ai 領先於 ai+1
稱 ai-1 是 ai 的前驅 , ai+1 是 ai 的後繼元素 . 當 i = 1 , 2 ... , n - 1 時候 , ai 有且僅有 一個 直接後
繼 , 當 i = 2 ,......., n 時候 , ai 有且僅有一個直接的前驅。
線性表的長度 : 線性表的元素的個數 n( n>=0 ) , 當 n = 0 時候 我們稱之為空表
線性表的ADT :
注意 : 這只是 抽象 層面 來說 , 也就是說實現方式儘管 有 順序表 和 連表等實現方式 , ADT僅僅抽取他們的相同
處 且 基本具有的操作 , 具體實現時候 , 可以新增Data 資料 , 可以 擴充 操作 或者新增 輔助方法( 抽取
相同程式碼 )。 對於實際問題中更復雜的操作 , 可以使用ADT中的基本操作來組合完成。
定義如下:
ADT 線形表 ( List ) Data : 下一層資料型別 + 描述 線性表的資料物件的序列 {a1,a2,a3,......, an} , 每個元素均為DataType , 其中 , 除了元素 a1 外 , 每一個 元素都只有唯一的前驅元素 , 除了an外 , 每個元素都只有唯一的後繼元素 。 元素之間的關係是一對一的關 系。 Operation: 操作+ 描述 (規定 : 提前說明 , 我們使用的編號 均從 0 開始 , 操作返回 0 代表成功 , -1 代表失敗) InitList(*L) : 初始化操作 , 給L 指標指向的List型別開闢能容納序列的空間 ListEmpty(L) : 若線性表為空 , 返回true else false ClearList(*L) : 將線效能表清空 GetElem(L , i ,*e) : 將線性表L中的第i個元素通過傳出引數e取出 , 返回值 0 代表的 成功 , -1 代表錯誤 LocateElem(L,e ) : 將線形表L 中查詢 第一個匹配到的e , 成功返回 編號位置 , 失敗返回-1 ListInsert(*L , i , e) : 線上性表第 i 個元素 的前面 插入一個元素 , 成功返回 0 失敗返回 -1 ListDelete(*L , i ,*e ): 刪除線性表中的第i個位置的元素 , 並用e返回其值 ListLength(L) : 返回線性表中的元素的個數 : endADT
線形表的順序儲存結構:
ADT -> 物理層面 -> 語言實現( C 語言實現):
指的是使用一段連續的儲存單元依次儲存線性表的資料元素。
sqList 結構體 定義在標頭檔案當中:
#ifndef __SEQ_LIST_H #define __SEQ_LIST_H #define MAXSIZE 20 /*假設順序表的容量為20*/ #define TRUE 0 /*我們只使用TRUE 和 FALSE 兩個量表示成功和失敗就行了 , 但是注意TRUE是0*/ #define FALSE -1 typedef int ElemType; /*假設ElemType 型別為int*/ typedef int BOOL; /*BOOL 表示兩個量 : TRUE | FALSE */ /*結構體的宣告放在*/ typedef struct { ElemType data[MAXSIZE]; int length; /*擴充了ATD的DATA,其表示指向序列最後一個元素的下一個位置*/ }sqList; /*函式的宣告放在這個位置 */ extern void InitList(sqList * L); extern BOOL ListEmpty(sqList L); extern void ClearList(sqList * L); extern int LocateElem(sqList L , ElemType e); extern int ListLength(sqList L); extern BOOL ListInsert(sqList * L , int i , ElemType e); extern BOOL ListDelete(sqList * L , int i , ElemType *e); extern int GetElem(sqList L , int i , ElemType * e); #endifsqList 結構體定義 以及 操作介面宣告
sqList 操作定義在 .c 檔案當中 :
/************************************************* Function: InitList Description: 初始化順序表的長度為 0 Output: *L : 線性表發生變動 Return: 空 TRUE | 非空FALSE (TRUE :0 FALSE:-1) *************************************************/ void InitList(sqList * L) { L->length = 0; } /************************************************* Function: LisEempty Description: 返回順序表是否為空 , O(1) 判斷 L->length 是否為0即可 Input: L : 線性表結構 Return: 空 TRUE | 非空FALSE (TRUE :0 FALSE:-1) *************************************************/ BOOL ListEmpty(sqList L) { return L.length ? FALSE : TRUE; } /************************************************* Function: ClearList Description: 將順序表清空 O(1) 將L->length 置為0即可 Output: *L : 線效能表發生變動 Return: void *************************************************/ void ClearList(sqList * L) { L->length = 0; } /************************************************* Function: LocateElem Description: 獲取第一次出現指定元素的位置 O(n) 開始遍歷判斷是否相等 返回下下標位置 Input: L : 順序表結構 e : 指定的元素 Return: int 具體位置 , 沒找到返回-1 *************************************************/ int LocateElem(sqList L , ElemType e) { int i = 0; for(;i < L.length ; ++i) { if(L.data[i] == e) return i; } return -1; } /************************************************* Function: ListLength Description: 獲取順序表的長度 O(1) 直接返回 L.length即可 Input: L 表結構 Return: int 順序表的長度 *************************************************/ int ListLength(sqList L) { return L.length; } /************************************************* Function: ListInsert Description: 在順序表的指定位置插入元素 : 時間複雜度O(n) : 時間浪費在移動上面 : 插入位置不合理 , return FALSE 如果 length + 1 > MAXSIZE return FALSE 需要將 i 到 length-1的元素向後移動一個位置 將元素插入指定位置後 , 表的長度 + 1 Input: i : i位置元素的前面進行插入 e : 被插入的元素 Output: *L: 傳出引數,表示線性表會被修改 Return: 成功 TRUE | 失敗 FALSE *************************************************/ BOOL ListInsert(sqList * L , int i , ElemType e) { int j = 0; if( 0>i || i > L->length || L->length + 1 > MAXSIZE) return FALSE; for(j = i+1 ; j <=L->length ; ++j) L->data[j] = L->data[j-1]; L->data[i] = e; L->length+=1; return TRUE; } /************************************************* Function: ListDelete Description: 刪除指定位置的元素 : O(n) 時間也是浪費在移動資料上面 : 如果刪除的位置不合適: return FALSE 取出刪除的元素 將 i 位置之後的元素都向前移動一個元素: 表的長度需要減去 1 Input: i : 刪除元素的位置 : 0<=i<=L->length-1 Output: L : 表會發生變動 e : 輸出被刪除的元素 Return: 刪除成功 TRUE | 失敗 FALSE *************************************************/ BOOL ListDelete(sqList * L , int i , ElemType * e) { int j = 0; if(0 == L->length || 0 > i || i >= L->length) return FALSE; *e = L->data[i]; for(j = i+1 ; j <=L->length ; ++j) { L->data[j-1] = L->data[j]; } L->length-=1; return TRUE; } /************************************************* Function: GetElem Description: 獲取順序表中指定位置的元素 , 時間複雜度O(n) , 時間浪費在遍歷上面: i位置不合理 return FALSE 取得i位置的元素 Input: L : 順序表結構 i : 獲取元素的位置 , 0<= i <= L.length-1 Output: *e : 輸出型別引數 , 獲取 i 指向的元素 Return: 成功TRUE | 失敗 FALSE *************************************************/ BOOL GetElem(sqList L , int i , ElemType * e) { /* i 是從0 開始計算的*/ if(0 == L.length || i < 0 || i > L.length-1) return FALSE; *e = L.data[i]; return TRUE; }sqList 操作的實現
宗上看出:
主要操作:
插入 , 刪除 O(n)
搜尋 , 修改 O(1)
線效能表儲存結構的優點和缺點:
- 優點:
- 無需為表中元素之間的邏輯關係增加額外空間(比如連表 , 需要增加一個指標域)
- 可以快速的存取表中 任意元素的位置
- 缺點:
- 插入 和 刪除操作需要移動大量元素
- 當線性表的長度變化較大時 , 難以確定儲存空間的容量
- 造成儲存空間的碎片 [ 可能開闢的空間大小 > 順序表的大小造成 空間的浪費 ]