線性表的鏈式表現和實現
線性表的鏈式表示和實現
【鏈式儲存結構】
結點在儲存器中的位置是任意的,即邏輯上相鄰的資料元素在物理上不一定相鄰
線性表的鏈式表示又稱為非順序映像或鏈式映像
用一組物理單位任意的儲存單元來存放線性表的資料元素。
這組儲存單元既可以是連續的,也可以是不連續的,甚至是零散分佈在記憶體中的任意位置上的。
連結串列元素的邏輯次序和物理次序不一定相同
單鏈表:指標域和資料域
頭指標:記錄第一個元素地址
單鏈表是由頭指標唯一確定,因此單鏈表可以用頭指標的名字來命名。
結點:資料元素的儲存映像,由資料域和指標域兩部分組成。
連結串列: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)