本篇及下一篇文章介紹線性表,包括線性表的定義及順序表和鏈表的表示和方法。有關b樹的補充等到之后進行介紹。
一:線性表的定義和基本操作
線性表是具有相同數據類型數據元素的有限序列集合,當線性表內沒有元素時,是一個空表用a(i)代表第i個數據元素,第一個元素為表頭,最后一個元素為表尾。除第一個元素外,每個元素都有一個直接前驅;除最后一個元素外,每個元素都有一個直接后繼。
線性表是一個邏輯結構,表示元素之間一一對應的關系;而順序表和鏈式表是指存儲結構。
線性表的基本操作是最基本的操作,包括:
InitList(&L):初始化一個空的線性表。
Length(L):求表長。
LocateElem(L,e):在表中查找給定關鍵字值的元素。
GetElem(L,i):在表中查找第i個位置的元素的值。
ListInsert(&L,i,e):在表中的第i個位置插入元素e。
ListDelete(&L,i,&e):刪除表中第i個位置元素,並用e返回。
PrintList(L):輸出線性表中的所有元素值。
Empty(L):判斷線性表是否為空。
DestoryList(&L):銷毀線性表,並釋放線性表所占用的內存空間。
這里的"&"表示的是c++里面的引用調用,傳入指針變量的時候要對傳入的指針進行改變,則會用到指針變量的引用型。在C語言的采用指針的指針也可以達到同樣的效果。
二:線性表的順序存儲
1.定義
線性表的順序存儲又稱順序表,用一組地址連續的存儲單元依次存儲線性表的數據元素,使邏輯上相鄰的元素物理位置上也相鄰。i為元素a(i)的位序,特點是表中的邏輯順序與其物理順序相同。
有關順序表的基本模型和結構這里就不詳細介紹了,主要是順序表是依靠數組實現的,要注意的是:線性表中元素的位序是從1開始的,而數組中元素的位序是從0開始的。
2.順序存儲數據類型
由於順序表是由數組實現的,我們知道一維數組可以是靜態分配的,也可以是動態分配的。靜態分配因為空間和大小有限,一旦占滿,再加入新的數據將會產生溢出,導致程序崩潰;動態分配,數組空間是在需要時通過動態存儲語句分配,可以不斷開辟新的存儲空間,擴充存儲空間,所以更高效。
順序存儲數據類型實現的代碼如下:
// 順序表的靜態存儲
#define MaxSize 50 //順序表最大長度
typedef struct{
ElemType data[MaxSize]; //順序表數據元素
int length; //順序表當前長度
}SqList; //順序表結構體類型定義
//順序表的動態存儲
#define InitSize 100 //表長度的初始定義
typedef struct{
ElemType *data; //動態分配數組指針
int MaxSize;length; //數組最大容量和當前個數
}SeqList; //順序表結構體類型定義
C語言初始動態分配語句是:
L.data= (ElemType)malloc(sizeof(ElemType)InitSize);
C++的動態分配語句是:
L.data = new ElemType(InitList);
3.順序表基本操作的實現(代碼寫的是靜態存儲,動態存儲類似)
(1)插入操作
在順序表L的第i個位置插入新元素e。如果i的輸入不合法,則返回false,表示插入失敗;否則將原順序表的第i個元素及其后面的所有元素右移一個位置,騰出一個空間插入新元素e。順序表的長度加一,插入成功,返回true。插入位置范圍從1到L.length+1,代碼如下:
bool ListInsert(SqList &L,int i,ElemType e){
if(i < 1|| i > Length + 1)
return false;
if(L.length >= MaxSize) //當前存儲空間已滿,不能插入
return false;
for(int j = L.length;j >= i;j--){ //將i及之后的元素后移
L.data[j] = L.data[j-1];
}
L.data[i-1] = e; //數組從0開始
L.length++;
return true;
}
插入操作的最好情況是在表尾插,后移操作不再進行;最壞情況是在表頭插,后移n次。而平均情況下,插入的平均時間復雜度是O(n)。
(2)刪除操作
刪除表中的第i個位置的元素,成功返回true,並將被刪除的元素用引用變量e返回,否則返回false,也需要移動元素位置。刪除位置范圍從1到L.length,代碼如下:
bool ListDelete(SqList &L,int i,ElemType &e){
if(i < 1|| i > Length)
return false;
e = L.data[i-1];
for(int j = i;j < L.length;j++){ //將i及之后的元素前移
L.data[j-1] = L.data[j];
}
L.length--;
return true;
}
插入操作的最好情況是在表尾插,前移操作不再進行;最壞情況是在表頭插,前移n-1個數據元素。而平均情況下,刪除的平均時間復雜度是O(n)。
(3)簡單的按值查找
在順序表中查找第一個元素值等於e的元素,並返回其位序。代碼如下:
int LocateElem(SqList L,ElemType e){
int i;
for(i = 0;i < L.length;i++)
if(L.data[i] == e)
return i + 1; //位序從一開始
return 0;
}
最好情況在表頭比較一次,在表尾或不存在比較n次,按值查找的平均時間復雜度為O(n)。
4.順序表的特點
優點:隨機訪問,在O(1)的時間內找到指定的元素。存儲密度高,每個結點只存儲數據元素。
缺點:插入和刪除操作需要移動大量元素。