線性表的順序存儲結構: 用一組地址連續的存儲單元依次存放線性表中的數據元素。
它是實現線性表最簡單的方法。
順序存儲結構的C語言描述:
對於線性表來說,可以開闢一個一維數組空間,來存儲線性表的數據元素。由於線性表本身的長度是可變的,所以需要一個參量來指示當前的長度(length,對應線性表的邏輯結構)。而對於數組來說,它應該有一個當前分配的存儲量(listsize,對應線性表的存儲結構)。
另外,順序存儲結構俗稱順序表。
#define LIST_INIT_SIZE 80 //線性表存儲空間的初始分配量
#define LISTINCREMENT 10 //線性表存儲空間的分配增量
typedef struct
{
ElemType *elem; //存儲空間基址
int length; //當前長度
int listsize; //當前分配的存儲容量;以sizeof(ElemType)爲單位
}SqList; //俗稱 順序表
在順序表表示的情況下進行的基本操作:
【初始化操作】
//構造一個空的線性表
Status InitList_Sq(SqList &L)
{
//給線性表的數據元素開闢一個一維的數組空間
L.elem = (ElemType*)malloc(LIST_INIT_SIZE * sizeof(ElemType));
if (!L.elem) exit(OVERFLOW);
L.length = 0;//初始時線性表是個空表,長度爲0
L.listsize = LIST_INIT_SIZE;//給定線性表的存儲空間的大小
return OK;
}//InitList_Sq
【查詢操作】
//在線型表L中找到第一個與e滿足特定關係的數據元素的位序(查詢操作)
int LocateElem_Sq(SqList L, ElemType e, Status(*compare)(ElemType, ElemType))
{
i = 1; //i的初值爲第1個元素的位序
p = L.elem; //p的初值爲第1個元素的存儲位置
while (i <= L.length && !(*compare)(*p++, e)) ++i;
if (i <= L.length) return i;
else return 0;
}//LocateElem_Sq
這個操作的時間複雜度爲:,其中,表示表長。
【插入操作】
插入元素時,線性表的邏輯結構發生了什麼變化?很顯然,(a1, … ai-1, ai, …, an)改變爲(a1, … ai-1, e, ai, …, an),這個變化體現在兩方面:(1)有序對<ai-1, ai>變成了有序對<ai-1, e>和<e, ai>;(2)長度增1。
這是相當於前i-1個元素(a1, … ai-1)不變,後n-i+1個元素(ai, …, an)後移一位,最終長度增1。
//在線性表中第pos個位置上插入元素e
Status ListInsert_Sq(SqList &L, int pos, ElemType e)
{
//算法的健壯性
if (pos<1 || pos>L.length + 1) return ERROR; //插入位置不合法
if (L.length >= L.listsize) //當前存儲空間已滿,增加分配
{
newbase = (ElemType *)realloc(L.elem, (L.listsize + LISTINCREMENT) * sizeof(ElemType));//數組空間的再分配
if (!newbase) exit(OVERFLOW);//存儲分配失敗
L.elem = newbase; //新基址
L.listsize += LISTINCREMENT;//增加存儲容量
}
//算法的主題
q = &(L.elem[pos - 1]); //q指示插入位置
for (p = &(L.elem[L.length - 1]); p >= q; --p)
*(p + 1) = *p;//插入位置及之後的元素右移
*q = e; //插入e
++L.length;//表長增1
return OK;
}
在第i個位置插入元素,移動元素的個數爲。
這個算法的時間複雜度爲:。
也可以考慮平均的情況:
假設在第i個元素之前插入的概率爲pi,則在長度爲n的線性表中插入一個元素,所需移動元素次數的期望值爲:
若假定在線性表中任何一個位置上進行插入的概率都是相等的,則移動元素的期望值爲:
爲表長的一半。
【刪除操作】
刪除元素時,線性表的邏輯結構發生什麼變化?很顯然,(a1, … ai-1, ai, ai+1, …, an)改變爲(a1, … ai-1, ai+1, …, an),這個變化也體現在兩個方面,與插入操作相反:(1)有序對<ai-1, ai>和<ai, ai+1>變成了有序對<ai-1, ai+1>;(2)表長減1。
這是相當於前i-1個元素(a1, … ai-1)不變,後n-i個元素(ai+1, …, an)前移一位,最終長度減1。
//在線性表L中刪除第pos個位置上的元素,並將刪除的元素賦值給e
Status ListDelete_Sq(SqList &L, int pos, ElemType &e)
{
//算法的健壯性
if ((pos < 1) || (pos > L.length)) return ERROR; //刪除位置不合法
//算法的主題
p = &(L.elem[pos - 1]); //p爲被刪除元素的位置
e = *p; //被刪除元素的位置賦給e
q = L.elem + L.length - 1;//表尾元素的位置
for (++p; p <= q; ++p)
*(p - 1) = *p; //被刪除元素之後的元素前移
--L.length; //表長減1
return OK;
}//ListDelete_Sq
時間複雜度是對於問題規模而言的,這時候需要忽略刪除元素這個因素。
所以,這個算法的時間複雜度爲:。
也可以考慮平均的情況:
假設刪除第i個元素的概率爲qi,則在長度爲n的線性表中刪除一個元素,所需移動元素次數的期望值爲:
若假定在線性表中任何一個位置上進行插入的概率都是相等的,則移動元素的期望值爲:
大致也爲表長的一半。
對順序表的總結:
【優點】
可以對每個數據元素進行隨機的存取,它的表長是顯值。
【缺點】
在插入和刪除數據元素的時候要進行元素的移動。每進行一次插入或刪除,都要大致移動表的一半的元素。