數據結構學習筆記(四)--順序表
順序表是用順序存儲方式實現的線性表。
點擊進入上一篇:數據結構學習筆記(三)--線性表的定義和基本操作
順序表的定義
順序表 --用順序存儲的方式實現的線性表
什么是順序存儲
順序存儲:把邏輯上相鄰的元素存儲在物理位置上也相鄰的存儲單元中,元素之間的關系由存儲單元的鄰接關系來體現。
圖形表示

順序表的實現方式
靜態分配
定義一個靜態數組存放數據元素。
代碼實現
用c語言舉例:
#include <stdio.h>
#define MaxSize 10 //定義最大長度
typedef struct{
in data[MaxSize]; //用靜態的“數組”存放數據元素
int length; //順序表的當前長度
} SqList; //順序表的類型定義(靜態分配方式),自定義命名
//基本操作 ——初始化一個順序表
void InitList(SqList &L){
for(int i=0;i<MaxSize;i++)
L.data[i] = 0; //將所有數據元素設置為默認初始值
L.length = 0; //順序表初始長度為0
}
注:如果沒有初始化數據結構,直接打印順序表,打印出來的數據未知(內存中的遺留數據,也稱臟數據)
靜態分配的特性
順序表的表長開始確定后無法更改(存儲空間是靜態的)
動態分配
使用指針相關知識和c語言malloc、free函數動態申請和釋放內存空間。
代碼實現
用c語言舉例:
#include <stdlib.h>
#define InitSize 10 //默認的最大長度
typedef struct{
int *data; //指示動態分配數組的指針
int MaxSize; //順序表的最大容量
int length; //順序表的當前長度
} SeqList;
//基本操作 ——初始化一個順序表
void InitList(SeqList &L){
//用malloc函數申請一片連續的存儲空間
L.data = (int *)malloc(InitSize * sizeof(int)); //注意類型轉換
L.length = 0;
L.MaxSize = InitSize; //初始化順序表最大長度
}
//基本操作 ——增加動態數組的長度
void IncreaseSize(SeqList &L,int len){
int *p = L.data; //創建一個指針將指向原data數據所在內存,類似於一個temp;
L.data = (int *)malloc((L.MaxSize+len)*sizeof(int));//給data分配一個新的,增大后的內存空間
//遍歷將原來的數據賦值給新的地址(時間開銷大)
for(int i=0;i<L.length;i++){
L.data[i] = p[i]; //將原data數據賦值給新的data
}
L.MaxSize = L.MaxSize +Len; //順序表最大長度增加 len,重新定義順序表最大長度
free(p); //釋放原來的內存空間
}
順序表的特點
- 隨機訪問,即可以在O(1)時間內找到第i個元素。
- 存儲密度高,每個節點只存儲數據元素。
- 拓展容量不方便(即便采用動態分配的方式實現,拓展長度的時間復雜度也比較高)。
- 插入、刪除操作不方便,需要移動大量元素。
順序表的基本操作
順序表的初始化
見順序表的實現方式中的代碼示例
順序表的插入
ListInsert(&L,i,e):插入操作。在表中第i個位置上插入指定元素e。
代碼實現
采用靜態分配的存儲方式,用c語言舉例:
bool ListInsert(SqList &L,int i,int e){
//首先判斷參數是否合理,保持代碼的健壯性
if(i<1 || i>L.length+1) //判斷i的范圍是否有效
return false;
if(L.length>=MaxSize)
return false;
for(int j=L.length;j>=1;j--) //將第i個元素及之后的元素后移
L.data[j] = L.data[j-1];
L.data[i-1] = e; //在指定位置i處放入e。(因為線性表是位序從1開始,代碼數組下標從0開始,故為i-1)
L.length++; //長度加1
return true;
}
插入操作的時間復雜度
- 最好情況:新元素插入到表尾,不需要移動元素,i = n+1,循環0次;最好時間復雜度 = O(1)
- 最壞情況:新元素插入到表頭,需要將原有的n 個元素全部向后移動,i = 1,循環n次;最壞時間復雜度 = O(n)
- 平均情況:假設新元素插入到任何一個位置的概率相同,即i = 1,2,3, ... ,length+1 的概率都是 p = 1/(n+1),計算構成等差數列求得,T(n) = n/2;平均時間復雜度 = O(n)
順序表的刪除
ListDelete(&L,i,&e):刪除指定位序上的元素,並用e帶回刪除數據的值。
代碼實現
采用靜態分配的存儲方式,用c語言舉例:
bool ListDelete(SqList &L,int i,int &e){
if(i<1 || i>L.length) //判斷i的范圍是否有效
return false;
e = L.data[i-1]; //將被刪除的元素賦值給e
for(int j=i;j<L.length;j++) //將第i個位置后的元素前移
L.data[j-1]=L.data[j];
L.length--; //線性表長度-1
return true;
}
刪除操作的時間復雜度
- 最好情況:刪除表尾元素,不需要移動其他元素,i = n,循環0次;最好時間復雜度 = O(1)
- 最壞情況:刪除表頭元素,需要將后續的n-1個元素全部向前移動,i = 1,循環 n-1次;最壞時間復雜度 = O(n)
- 平均情況:假設刪除任何一個元素的概率相同,即i = 1,2,3, ... ,length 的概率都是 p = 1/n,計算構成等差數列求得,T(n) = (n-1)/2;平均時間復雜度 = O(n)
注意事項
刪除位序為i的元素和刪除數組下標為i的元素並不相同,前者從1開始,后者從0開始。
順序表的查找
按位查找
GetElem(L,i):按照順序表位序查找數據的值,並返回數據的值。
代碼實現
采用靜態分配的存儲方式,用c語言舉例:
int GetElem(SqList L,int i){
return L.data[i-1]; //直接返回該位序所在數組下標的值
}
注:因調用malloc函數的內存分配和定義數組的內存分配方式相似,故動態分配與靜態分配的按位查找都是如此,以查詢數組下標的形式實現。
時間復雜度
按位查找的時間復雜度:O(1) (體現順序表“隨機存取”的特性)
按值查找
LocateElem(L,e):在表中查找具有給定關鍵字值的元素,並返回其位序
代碼實現
采用靜態分配的存儲方式(當然,動態也是這么做),用c語言舉例:
int LocateElem(SqList L,int e){
for(int i=0;i<L.length;i++){
if(L.data[i]==e)
return i+1; //數組下標為i的元素值等於e,返回其位序i+1
}
return 0; //循環結束還沒找到,說明查找失敗
}
時間復雜度
- 最好情況:目標元素在表頭,循環1次;最好時間復雜度 = O(1)
- 最壞情況:目標元素在表尾,循環n次;最壞時間復雜度 = O(n)
- 平均情況:假設目標元素出現在任何一個位置的概率相同,都是1/n,平均循環次數 = (n+1)/2,平均時間復雜度 = O(n)
注意事項
《數據結構》考研初試中,手寫代碼可以直接用 “==”,無論e的數據類型是基本數據類型還是結構類型。
手寫代碼主要考察學生是否能理解算法思想,不會嚴格要求代碼完全可運行。
但如果有的學校考《C語言程序設計》,那么對語法要求就會更加嚴格。
