數據結構導論之第二章(線性表)


 一、線性表的基本概念

線性表是由n(n≥0)個數據元素(結點)a1,a2,a3,……an組成的有限序列;數據元素的個數n定義為表的長度。當n=0時,稱為空表。

將非空的線性表(n>0)記作:L=(a1,a2,a3,……,an)

  • a1:起始結點(沒有直接前驅)
  • an:終端結點(沒有直接后繼)。
  • a1稱為a2的直接前驅
  • a3稱為a2的直接后繼

線性表的特點:

  • 線性表中只有1個起始結點,1個終端結點,
  • 起始結點沒有直接前驅,有1個直接后繼。
  • 終端結點有1個直接前驅,沒有直接后繼。
  • 除這2個結點外,每個結點都有且只有1個直接前驅和1個直接后繼。

線性表的基本運算

  • 1,初始化 Initiate(L) :建立一個空表L=(),L不含數據元素。
  • 2,求表長度 Length(L):返回線性表L的長度。
  • 3,取表元 Get(L,i):返回線性表第i個數據元素,當i不滿足1≤i≤Length(L)時,返回一特殊值。
  • 4,定位 Locate(L,x):查找線性表中數據元素值等於x的結點序號,若有多個數據元素值與x相等,運算結果為這些結點中序號的最小值,若找不到該結點,則運算結果為0。
  • 5,插入 Insert(L,x,i):在線性表L的第i個數據元素之前插入一個值為x的新數據元素,參數i的合法取值范圍是1≤i≤n+1。操作結束后線性表L由(a1,a2,…,ai-1,ai,ai+1,.…,an )變為(a1,a2,…,ai-1,x,ai,ai+1 .…,an )表長度加1。
  • 6,刪除 Delete(L,i):刪除線性表L的第i個數據元素ai ,i的有效取值范圍是1≤i≤n。刪除后線性表L由(a1,a2,…,ai-1,ai,ai+1,.…,an )變為(a1,a2,…,ai-1,ai+1,.…,an ),表長度減1

二、線性表的順序存儲

線性表順序存儲的方法:將表中的結點依次存放在計算機內存中一組連續的存儲單元中。

  • ◆ 數據元素在線性表中的鄰接關系決定其在存儲空間中的存儲位置。
  • ◆ 即邏輯結構中相鄰的結點,其物理存儲位置也相鄰。
  • ◆ 用順序存儲實現的線性表稱為順序表。一般使用數組存儲

順序存儲結構的特點:

  • 線性表的邏輯結構與存儲結構一致
  • 可以對數據元素實現隨機讀取
  • 設線性表中所有結點的類型相同,則每個結點所占用存儲空間大小亦相同。
  • 假設表中每個結點占用L個存儲單元,其中第一個單元的存儲地址則是該結點的存儲地址
  • 並設表中開始結點a1 的存儲地址是d,那么結點ai 的存儲地址LOC(ai)=d+(i-1)*L

順序表是用一維數組實現的線性表,數組下標可以看成是元素的相對地址;邏輯上相鄰的元素,存儲在物理位置也相鄰的單元中

1、線性表的基本運算在順序表上的實現

=======================插入========================

插入 Insert(L,x,i):在線性表L的第i個數據元素之前插入一個值為x的新數據元素,參數i的合法取值范圍是1≤i≤n+1。操作結束后線性表L由(a1,a2,…,ai-1,ai,ai+1,.…,an )變為(a1,a2,…,ai-1,x,ai,ai+1 .…,an )表長度加1。

注意:

  • 當表空間已滿,不可再做插入操作。
  • 當插入位置是非法位置,不可做正常的插入操作。

順序表插入操作過程

  • ① 將表中位置為n ,n-1,…,i上的結點,依次后移到位置n+1,n,…,i+1上,空出位置i。
  • ② 在位置i上插入新結點x。(當插入位置i=n+1時,無須移動結點,直接將x插入表的末尾)
  • ③ 該順序表長度加1。

結論:

  • 假設線性表中含有n個數據元素,在進行插入操作時,有n+1個位置可插入,在每個位置插入數據的概率是:1/(n+1),在i位置插入時,要移動n-i+1個數據
  • 假定在n+1個位置上插入元素的可能性均等,則平均移動元素的個數為:n/2,平均時間復雜度O(n)

 ===================刪除========================

刪除 Delete(L,i):刪除線性表L的第i個數據元素ai ,i的有效取值范圍是1≤i≤n。刪除后線性表L由(a1,a2,…,ai-1,ai,ai+1,.…,an )變為(a1,a2,…,ai-1,ai+1,.…,an ),表長度減1

注意:當要刪除元素的位置i不在表長范圍內(即i<1或i>L->length)時,為非法位置,不能做正常的刪除操作

順序表刪除操作過程:

  • 1,若i=n,則只要刪除終端結點,無須移動結點;
  • 2,若1≤i≤n-1,則必須將表中位置i+1,i+2,…,n的結點,依次前移到位置i,i+1,…,n-1上,以填補刪除操作造成的空缺。
  • 3,該表長度減1

刪除算法的分析

  • 假設線性表中含有n個數據元素,在進行刪除操作時,有n個位置可刪除;每個位置刪除數據的概率是:1/n,在i位置刪除時,要移動n-i個數據;
  • 假定在n個位置上刪除元素的可能性均等,則平均移動元素的個數為:(n-1)/2;平均時間復雜度O(n)

 插入和刪除的結論:順序存儲結構表示的線性表,在做插入或刪除操作時,平均需要移動大約一半的數據元素。當線性表的數據元素量較大,並且經常要對其做插入或刪除操作時,這一點需要值得考慮。

===================定位=================

定位(查找):定位運算LocateSeqlist(L,X)的功能是求L中值等於X的結點序號的最小值,當不存在這種結點時結果為0。

算法的過程:從第一個元素 a1 起依次和x比較,直到找到一個與x相等的數據元素,則返回它在順序表中的存儲下標或序號;或者查遍整個表都沒有找到與 x 相等的元素,返回0。

算法分析:

  •  最好情況下,第1個元素就是x值,此時查找比較次數為1。
  •  最壞情況下,最后1個元素是x值,此時查找比較次數為n。
  •  故平均查找長度為(n+1)/2。平均時間復雜度O(n)

三、線性表的鏈接存儲

鏈式存儲的結構:數據項 + 指針項

鏈表(Link List):使用鏈式存儲的線性表

鏈表的具體存儲表示為:用一組任意的存儲單元來存放; 鏈表中結點的邏輯次序和物理次序不一定相同,還必須存儲指示其后繼結點的地址信息。

 

所有結點通過指針鏈接而組成單鏈表

NULL稱為空指針

Head稱為 頭指針變量,存放鏈表中第一個結點地址;在單鏈表中,增加頭結點的目的是方便運算的實現

鏈表的表示:由於我們常常只注重結點間的邏輯順序,不關心每個結 點的實際位置,可以用箭頭來表示鏈域中的指針,單鏈表就 可以表示為下圖形式。

 單鏈表特點:

❖ 起始節點又稱為首結點,無前驅,故設頭指針head 指向開始結點。

❖ 鏈表由頭指針唯一確定,單鏈表可以用頭指針的名字 來命名。頭指針名是head的鏈表可稱為表head。

❖ 終端結點又稱尾結點,無后繼,故終端結點的指針域 為空,即NULL

❖ 除頭結點之外的結點為表結點

❖ 為運算操作方便,頭結點中不存數據

單鏈表的基本運算

=====================初始化=====================

空表由一個頭指針和一個頭結點組成;在算法中,變量head是鏈表的頭指針,它指向新創建的結點,即頭結 點。一個空單鏈表僅有一個頭結點,它的指針域為NULL。

 

 ====================求表長====================

在單鏈表存儲結構中,線性表的長度等於單鏈表所 含結點的個數(不含頭結點)

步驟:
1,令計數器j為0
2,令p指向頭結點
3,當下一個結點不空時,j加1,p指向下一個結點
4,j的值即為鏈表中結點個數,即表長度

=================讀表元素:查找第i個結點============
步驟:
1、令計數器j為0
2、令p指向頭結點
3、當下一個結點不空時,並且j<i 時,j加1,p指向下一個結點
4、如果j等於i,則p所指結點為要找的第i結點否則,鏈表中無第i結點

===============定位=================

定位運算是對給定表元素的值,找出這個元素的位置。對 於單鏈表,給定一個結點的值,找出這個結點是單鏈表的 第幾個結點。定位運算又稱為按值查找。

具體步驟:
1、令p指向頭結點
2、令i=0
3、當下一個結點不空時,p指向下一個結點,同時i的值加1
4、直到p指向的結點的值為x,返回i+1的值。
5、如果找不到結點值為x的話,返回值為0

 

 ===================插入====================

 

===========刪除===========

刪除運算是將表的第i個結點刪去。

(1)找到ai-1的存儲位置p

(2)令p->next指向ai的直接后繼結點

(3)釋放結點ai的空間,將其歸還給"存儲池" 。 

 free(p)是必不可少的,因為當一個結點從鏈表移出后,如果不釋放它的空間,它將變成一個無用的結點,它會一直占用着系統內存空間,其他程序將無法使用這塊空間。

 四、單項循環鏈表

普通鏈表的終端結點的next值為NULL;循環鏈表的終端結點的next指向頭結點,在循環鏈表中,從任一結點出發能夠掃描整個鏈表。

 

如何找到循環鏈表的尾結點:在循環鏈表中附設一個 rear 指針指向尾結點,適用於經常使用頭尾結點的鏈表操作中

若p為指向循環鏈表中某鏈結點的指針變量,判斷循環鏈表是否只有一個結點的標志是:p->next=p

五、雙向循環鏈表

在鏈表中設置兩個指針域,一個指向后繼結點,一個指向前驅結點這樣的鏈表叫做雙向鏈表

 

 雙向循環鏈表適合應用在需要經常查找結點的前驅和后繼的場合。找前驅和后繼的復雜度均為:O(1)

雙向鏈表中結點的刪除:設p指向待刪結點,刪除*p可通過下述語句完成:

  • (1)p->prior->next=p->next; //p前驅結點的后鏈指向p的后繼結點
  • (2)p->next->prior=p->prior; //p后繼結點的前鏈指向p的前驅結點
  • (3)free(p); //釋放*p的空間;(1)、(2)這兩個語句的執行順序可以顛倒。

雙向鏈表中結點的插入:在p所指結點的后面插入一個新結點*t,需要修改四個指針

  • (1)t->prior=p;
  • (2)t->next=p->next;
  • (3)p->next->prior=t;
  • (4)p->next=t;

六、順序實現與鏈式實現的比較

線性表與鏈表的優缺點:
(1)單鏈表的每個結點包括數據域與指針域,指針域需要占用額外空間。
(2)從整體考慮,順序表要預分配存儲空間,如果預先分配得過大,將造成浪費,若分配得過小,又將發生上溢;單鏈表不需要預先分配空間,只要內存空間沒有耗盡,單鏈表中的結點個數就沒有限制。

(3)、插入、刪除操作,順序表需要移動元素,而鏈表不需要移動元素

時間性能的比較

順序表

  • 讀表元 O(1)
  • 定位(找x) O(n)
  • 插入O(n)
  • 刪除O(n)

鏈表

  • 讀表元O(n)
  • 定位(找x)O(n)
  • 插入O(n)
  • 刪除O(n)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM