1. 程式人生 > 其它 >線性表的鏈式表現和實現

線性表的鏈式表現和實現

線性表的鏈式表示和實現

【鏈式儲存結構】

結點在儲存器中的位置是任意的,即邏輯上相鄰的資料元素在物理上不一定相鄰

線性表的鏈式表示又稱為非順序映像或鏈式映像

用一組物理單位任意的儲存單元來存放線性表的資料元素。

這組儲存單元既可以是連續的,也可以是不連續的,甚至是零散分佈在記憶體中的任意位置上的。

連結串列元素的邏輯次序和物理次序不一定相同

單鏈表:指標域和資料域

頭指標:記錄第一個元素地址

單鏈表是由頭指標唯一確定,因此單鏈表可以用頭指標的名字來命名。

結點:資料元素的儲存映像,由資料域和指標域兩部分組成。

連結串列:n個節點由指標鏈組成一個連結串列它是線性表的鏈式儲存映像,稱為線性表的鏈式儲存結構

連結串列分類:單鏈表、雙向連結串列、迴圈連結串列

結點只有一個指標域的連結串列,稱為單鏈表或線性連結串列

結點由兩個指標域的連結串列,稱為雙鏈表

首位相接的連結串列稱為迴圈連結串列(尾結點的後繼指標域存放頭節點或者首元結點的地址)

頭指標:是指向連結串列中第一個結點的指標

首元結點:是指連結串列中儲存第一個資料元素a1的結點

頭節點:是在連結串列的首元結點之前附設的一個結點

【不帶頭結點】

頭指標直接指向首元結點

【帶頭結點】

頭指標指向頭節點,頭指標指標域儲存首元結點地址

如何表示空表

無頭結點時,頭指標為空時表示空表用 ^表示

有頭結點時,當頭節點的指標域為空時表示空表

為什麼加頭節點

【1】便於處理首元結點的處理

首元結點的地址儲存在頭節點的指標域中,所以連結串列的第一個位置上的操作和其他位置一致,無須進行特殊處理.

【2】便於空表和非空表的統一處理

無論連結串列是否為空,頭指標都是指向頭節點的非空指標,因此空表和非空表的處理也就統一了。

頭節點的資料域內裝的是什麼?

頭節點的資料域可以為空,也可以放線性表長度等附加資訊,但此節點不能計入連結串列長度值

連結串列的特點:

(1)結點在儲存器中位置是任意的,即邏輯上相鄰的資料元素在物理上不一定相鄰

(2)訪問時只能通過頭指標進入連結串列,並通過每個結點的指標域依次向後順序掃描其餘結點,所以尋找第一個結點和最後一個結點所花費的時間不等。

連結串列-》順序存取(必須從頭開始一個一個找)

【帶頭結點單鏈表】

單鏈表是由表頭唯一確定,因此單鏈表可以用頭指標的名字來命名,若頭指標名是l,則稱連結串列為表l

單鏈表初始化:
生成新結點做頭結點,用頭指標L指向頭結點。

將頭結點的指標域置空

判斷連結串列是否為空(連結串列種無元素,稱為空連結串列(頭指標和頭結點仍存在))

【思路】判斷頭結點指標域是否為空

單鏈表的銷燬:連結串列銷燬後不存在

【思路】從頭指標開始,依次釋放所有結點

清空連結串列

連結串列任然存在,但連結串列中無元素,成為空連結串列(頭指標和頭結點仍然在)

【演算法思路】依次釋放所有結點,並將頭結點指標域設定為空

求單鏈表表長

【思路】從首元結點,依次計數所有結點

取值:取單鏈表種第i個元素的內容

從連結串列的頭指標出發,順著鏈域next逐個結點往下搜尋,直至搜尋到第i個結點為止。因此,連結串列不是隨機儲存結構

查詢:按值查詢:根據指定資料獲取資料所在位置(地址)O(n)

按值查詢:根據指定資料獲取資料所在的位置序號

插入:在第i個結點前插入新節點O(1)

先建立一個結點,插入資料寫在裡面資料域,(先)建立結點後繼指向第i個結點,(後)插入位置結點前結點後繼指向建立結點。

先後順序不能變,會丟失原來結點地址

如果要換需要藉助其他結點

刪除:刪除第i個結點O(1)(只修改指標)

如果要在單鏈表中進行前插或刪除操作,由於要從查詢前驅結點,所耗時間複雜度O(n)

【思路】找到元素,如果刪除元素有用儲存

將刪除元素都節點地址給刪除元素前結點

p->next=p->next->next

單鏈表的建立:

頭插法:(元素插入連結串列頭部)O(n)

尾插法:O(n)

從一個空表L開始,將新結點逐個插入到連結串列的尾部,尾指標r指向連結串列的尾結點

初始時,r同L均指向頭結點。每讀入一個數據元素則申請一個新節點,將新節點插入到尾結點後,r指向新結點

迴圈連結串列

尾結點指標域指向頭結點

優點:從表種任一結點出發都可以找到表中其他結點

雙向連結串列

為什麼要討論雙向連結串列

單鏈表的結點->y有指示後繼的指標域->找後繼結點方便;

即:查詢某結點的後繼結點的執行時間為O(1)

無指示前驅的指標域->找前驅結點難:從表頭出發查詢

即:查詢某結點的前驅結點的執行時間為O(n)

【解決方法】可以用雙向連結串列來克服單鏈表的這種缺點

雙向連結串列:在單鏈表的每個結點再增加一個指向其直接前驅的指標域prior,這樣連結串列中就形成了由兩個方向不同的鏈,故稱為雙向連結串列

雙向連結串列定義三個成員(兩個指標域,一個數據域 )

空表情況下頭結點兩個指標域都為空

頭指標的前驅指標域為空,最後一個結點後繼為空

雙向迴圈連結串列

和單鏈表的迴圈類似,雙向連結串列也可以有迴圈表

讓頭結點的前驅指標指向連結串列的最後一個結點

讓最後一個結點的後繼指標指向頭結點

雙向連結串列結構的對稱性

p->prior->next=p=p->next->prior

在雙向連結串列中有些操作(如:ListLength、GetElem等),因僅涉及一個方向的指標,故它們的演算法與線性連結串列的相同。但在插入、刪除時。則需要同時修改兩個方向上的指標,兩者的操作的時間複雜度均為O(n)

雙向連結串列的插入

順序表和連結串列的比較

鏈式儲存結構的優點:
結點空間可以動態申請和釋放

資料元素的邏輯次序靠結點的指標來指示,插入和刪除時不需要移動資料元素

鏈式儲存結構的缺點

儲存密度小,每個結點的指標域需額外佔用儲存空間。當每個結點的資料域所佔位元組不多時,指標域所佔儲存空間的比重顯得很大

儲存密度=結點資料本身佔用空間/結點佔用的空間總量

一般,儲存密度越大,儲存空間的利用率就越高。顯然,順序表的儲存密度為1(100%),而連結串列的儲存密度小於1

鏈式儲存結構式分隨機存取的結構。對任一節點的操作都要從頭指標依指標鏈查詢到該結點,這增加了演算法的的複雜度

線性表的應用

線性表的合併

問題描述:

​ 假設利用兩個線性表La和Lb分別表示兩個集合A和B,現要求一個新的集合A=A交B

La=(7,5,3,11) Lb=(2,6,3)---->La=(7,5,3,11,2,6)

有序表的合併

問題描述:

已知線性表La和Lb中的元素按值非遞減有序排列,現要求將La,Lb歸併為一個新的線性表Lc,且Lc中的資料元素仍按值非遞減有序排列

La=(1,7,8) Lb=(2,4,6,8,10,11)-->Lc=(1,2,4,6,7,8,8,10,11)