資料結構(一) 線性表的順序儲存和鏈式儲存

2021-09-22 22:33:34 字數 3555 閱讀 5972

線性表(list) :零個或多個資料元素的有限系列。

線性表有兩個重要的特性:1)線性表中元素的個數是有限的;

2)線性表中每個元素是有序的;in another opinon,  除第乙個元素無前驅節點,最後乙個元素無後繼節點之外,每乙個元素都有且只有乙個前驅節點和乙個後繼結點(這句話其實只是針對最基礎的線性表,例如:迴圈鍊錶每個元素都有前驅節點和後繼節點)。

線性表的實現可以採用順序儲存的方式,也可以採用鏈式儲存的方式。

1)線性表的順序儲存就是使用一塊連續的記憶體空間進行儲存。一般而言我們是使用乙個固定長度的陣列來實現的。抽象定義如下:

#define list_max_length  ***         //線性表中可以儲存的最大元素個數

typedef int elemtype; //元素型別

typedef struct sqlist;

2)由於採用順序儲存的方式,需要實現分配固定大小的連續空間(指定list_max_length),這就需要實現確定該鍊錶的大概長度範圍,否則可能因開闢空間太小造成線性表的溢位或者開闢空間太大的浪費。

3)對順序儲存的線性表進行插入操作時:在插入元素時線性表可能已滿,再行儲存可能造成溢位,因此需要進行線性表已滿的判斷處理;在進行刪除操作的時候,如果線性表為空,則根本無需進行刪除操作。 對於順序儲存,如果進行插入操作,需要將後續元素進行統一後移,這個平均的時間複雜度為o(n/2), 刪除操作也是同樣,需要將該元素之後的所有元素進行前移,平均的時間複雜度也是o(n/2),  這就導致了順序儲存不適於頻繁的插入和刪除操作,而對於查詢操作無論元素在前還是在後面可以通過陣列的下標進行直接的訪問。

1)鏈式儲存就是採用鍊錶的方式對線性表進行儲存。 抽象的節點定義如下:

/*  線性表之鏈式儲存*/

typedef struct linklist_linklist_st, *linklist_pt;

2)頭結點和頭指標:

頭結點並不是必須的,它的存在是為了方便對第乙個(也就是a1結點)的處理:操作如下

/*

* 1. 無頭鍊錶的插入linklistinsert:

* l: 煉表頭指標的位址

* data: 待插入的元素資料

* i: 位置

*/int linklistinsert(linknode_pt *l, elemtype data, int i)

if(!p || n>i) return -1; /*out of range*/

if(!(node = (linknode_pt)malloc(sizeof(linknode_st))))

}node->data = data; /*假定為簡單的資料型別,直接進行賦值操作*/

if(n=1)else

return 0;}/*

* 2. 有頭鍊錶的插入linklistinsert:

* l: 煉表頭指標的位址

* data: 待插入的元素資料

* i: 位置

*/int linklistinsert(linknode_pt *l, elemtype data, int i)

if(!p || n>i) return -1; /*out of range*/

if(!(node = (linknode_pt)malloc(sizeof(linknode_st))))

}node->data = data; /*假定為簡單的資料型別,直接進行賦值操作*/

return 0;

}

從上述**中可以看出: 頭結點的存在是為了方便對鍊錶進行無差別的操作(主要實在插入和刪除操作時),不用再區別對待第乙個結點和其他節點; 但是頭結點不是必需的,無頭的鍊錶依然可以正常操作,但是得單獨處理第乙個節點。

3)二級指標的疑問

值傳遞只是將該變數a的值傳遞給函式的形參b,而函式的形參b將值存到自己的記憶體中,自己值得改變只會影響b自己, 而不會影響到a的值;

位址傳遞則是將變數a的位址傳遞給形參b, 此時的b是個指標,而b的值則為變數a的位址,也就是說,b指向a; 因此當變數b的值改變後會影響到a的值;

現在把位址傳遞進行公升級: 如果我們只關心、使用乙個指標的值,則可以採用值傳遞,但是此時的值是指標本身,但它依然是值傳遞; 而如果我們要修改該指標的值,則需要位址傳遞,需要把該指標的位址傳遞給形參,而我們則可以通過修改形參的值改變整個指標的指向,這裡的指標的位址便是二級指標。

那為什麼資料結構中有的函式傳遞的是一級指標即頭指標,有的時候是二級指標即頭指標的位址呢?

這個主要的原因在於看是否需要更改頭指標的值,那問題又來了,什麼時候需要更改頭指標的只能?

答案有以下幾種:

a. 無頭鍊錶採用頭插法、頭刪法時,使用移動頭指標;

b. 整個鍊錶的建立、刪除過程可以通過移動頭指標來簡單的實現(此時不區分由頭無頭鍊錶)   

目前只想到了兩種。 當然有頭鍊錶的刪除可以不採用這種方式,但是得維持乙個pre指標,這個被大嬸linus
void remove_if(node ** head, remove_fn rm)

else /*如果為頭節點,則cur指向頭節點的指標域*/

curr = &entry->next;/*不刪除頭節點*/

}}/*

* 上述**的執行效果是:二級指標cur指向頭結點的指標域,每次判斷如果不是頭結點,則更改頭結點指標域的值,即將頭結點的指標通過entry指向下乙個節點,然後釋放entry節點。再次迴圈時,將頭結點指標域的值給entry,即entry指向下乙個節點,如此迴圈... ...

***/

線性表兩種儲存結構敘述完畢。

附上自己畫的圖:

附圖一:

附圖二:

附圖三:

附圖四:

附圖五:

附圖六:

一 線性表以及線性表的順序儲存結構

1 線性表的定義 2 線性表的性質 3 順序儲存結構 線性表的順序儲存結構,指的是用一段位址連續的儲存單元依次儲存線性表的資料元素。4 插入元素 演算法描述 5 刪除元素 演算法描述 6 可復用順序線性表 例項 相關操作的定義 ifndef seqlist h define seqlist h in...

資料結構 一 線性表

一 線性表的定義 線性結構的特點是 在資料元素的非空有限集中,1 存在唯一的乙個被成為 第乙個 的資料元素 2 存在唯一的乙個被成為 最後乙個 的資料元素 3 除了第乙個之外,其他的元素均只有乙個前驅,除了最後乙個以外,其他的元素均只有乙個後繼 線性表是最常用且最簡單的一種資料結構,乙個線性表是n個...

資料結構學習(一)線性表 順序表

線性表定義 線性表是由n個性質相同的資料元素組成的有序序列,n代表線性表長度。線性表內部節點都有且只有乙個直接前驅和直接後驅。eg 字串 pomme 構成線性表 p,o,m,m,e 根據線性表內的儲存形式可分為 順序表 和 鍊錶 兩種型別。1.1 順序表概念 用一組位址連續的儲存單元依次儲存各元素。...