王道408数据结构——第二章 线性表
文章目錄
- 一、線性表的定義和基本操作
- 線性表
- 順序表
- 1.插入操作
- 2.刪除操作
- 3.按值查找(順序查找)
- 二、單鏈表
- 1. 頭插法
- 2. 尾插法
- 3. 按序號查找
- 4. 按值查找
- 5. 插入結(jié)點(diǎn)
- 6. 刪除結(jié)點(diǎn)
- 7. 求表長
- 三、 雙鏈表
- 1. 插入
- 2. 刪除
- 四、循環(huán)鏈表
- 五、靜態(tài)鏈表
- 六、順序表和鏈表的比較
- 七、特殊矩陣的壓縮儲(chǔ)存
- 數(shù)組的定義
- 數(shù)組的存儲(chǔ)結(jié)構(gòu)
- 矩陣的壓縮存儲(chǔ)
- 1. 對稱矩陣
- 2. 三角矩陣
- 3. 三對稱矩陣(帶狀矩陣)
- 4. 稀疏矩陣
- 八、廣義表
- 廣義表的定義
- 廣義表的操作
一、線性表的定義和基本操作
線性表
線性表是具有相同數(shù)據(jù)類型的n個(gè)數(shù)據(jù)元素的有限序列,其中n為表長,n=0是為一個(gè)空表。除第一個(gè)元素外,每一個(gè)元素有且僅有一個(gè)直接前驅(qū),除最后一個(gè)元素外,每一個(gè)元素有且僅有一個(gè)直接后驅(qū)。
順序表
線性表的順序存儲(chǔ)稱為順序表,是用一組地址連續(xù)的存儲(chǔ)單元一次存儲(chǔ)線性表中的數(shù)據(jù)結(jié)構(gòu),從而使得邏輯上相鄰的兩個(gè)元素在物理位置上也相鄰。
線性表的位序是從1開始的,而數(shù)組元素的下標(biāo)從0開始。
1.插入操作
最好情況:表尾插入,時(shí)間復(fù)雜度O(1)
最壞情況:表頭插入,時(shí)間復(fù)雜度O(n)
平均情況:n/2
平均時(shí)間復(fù)雜度:O(n)
2.刪除操作
最好情況:刪除表尾元素,時(shí)間復(fù)雜度O(1)
最壞情況:刪除表頭元素,時(shí)間復(fù)雜度O(n)
平均情況:(n-1)/2
平均時(shí)間復(fù)雜度:O(n)
順序表插入和刪除的時(shí)間主要耗費(fèi)在移動(dòng)元素上,而移動(dòng)元素的個(gè)數(shù)取決于插入刪除元素的位置。
3.按值查找(順序查找)
最好情況:查找的元素在表頭,時(shí)間復(fù)雜度O(1)
最壞情況:查找的元素在表尾或不存在,時(shí)間復(fù)雜度O(n)
平均情況:(n+1)/2
平均時(shí)間復(fù)雜度:O(n)
二、單鏈表
線性表的鏈?zhǔn)酱鎯?chǔ)又稱單鏈表,指通過一組任意的存儲(chǔ)單元來存儲(chǔ)線性表中的數(shù)據(jù)元素。對每個(gè)鏈表結(jié)點(diǎn),除存放元素自身信息外,還需要存放一個(gè)指向其后繼節(jié)點(diǎn)的指針。
利用單鏈表可以解決順序表需要大量連續(xù)存儲(chǔ)單元的缺點(diǎn),但單鏈表附加指針域,存在浪費(fèi)空間的缺點(diǎn)。由于單鏈表的元素離散地分布在存儲(chǔ)空間中,所以單鏈表是非隨機(jī)存取的存儲(chǔ)結(jié)構(gòu)。
如果要訪問某個(gè)結(jié)點(diǎn)的前去前驅(qū)結(jié)點(diǎn),只能從頭開始遍歷。
頭節(jié)點(diǎn):在單鏈表的第一個(gè)結(jié)點(diǎn)前附加一個(gè)結(jié)點(diǎn)。頭結(jié)點(diǎn)可以不設(shè)任何信息,也可以記錄表長等信息。引入頭結(jié)點(diǎn)可以帶來兩個(gè)優(yōu)點(diǎn):
1. 頭插法
將新結(jié)點(diǎn)插入當(dāng)前鏈表的表頭,即頭結(jié)點(diǎn)之后。
讀入數(shù)據(jù)的順序和生成鏈表中的元素順序是相反的,總時(shí)間復(fù)雜度為O(n)
2. 尾插法
增加一個(gè)尾指針,使其始終指向當(dāng)前鏈表的尾結(jié)點(diǎn)。可使導(dǎo)入數(shù)據(jù)和鏈表元素的順序一致,總時(shí)間復(fù)雜度為O(n)。
3. 按序號查找
時(shí)間復(fù)雜度O(n)
4. 按值查找
時(shí)間復(fù)雜度O(n)
5. 插入結(jié)點(diǎn)
插入結(jié)點(diǎn)的代碼片段如下
p = getElem(L, i-1); // 移動(dòng)到插入位置前一個(gè)結(jié)點(diǎn) s->next = p->next; p->next = s;算法時(shí)間開銷主要在于查找第i-1個(gè)元素,時(shí)間復(fù)雜度為O(n);如果在給定結(jié)點(diǎn)后插入,時(shí)間復(fù)雜度僅為O(1)。
6. 刪除結(jié)點(diǎn)
代碼片段如下
p = getElem(L, i-1); q = p->next; p->next = q->next; free(q); // 第二、三步順序不能顛倒該算法的時(shí)間復(fù)雜度也耗費(fèi)找查找操作上,時(shí)間復(fù)雜度為O(n)。
7. 求表長
時(shí)間復(fù)雜度O(n)
三、 雙鏈表
雙鏈表結(jié)點(diǎn)有兩個(gè)指針,分別指向其前驅(qū)結(jié)點(diǎn)和后繼結(jié)點(diǎn)。
1. 插入
在p所指結(jié)點(diǎn)之后插入*s
s->next = p->next; p->next->prior = s; s->prior = p; p->next = s; /// 第一、二步必須在第四步之前2. 刪除
在p后刪除q
p->next = q->next; q->next->prior = p; free(q);四、循環(huán)鏈表
將單鏈表最后一個(gè)結(jié)點(diǎn)的指針改為指向頭結(jié)點(diǎn),形成循環(huán)單鏈表。判空條件是頭結(jié)點(diǎn)的指針是否指向自身。
循環(huán)單鏈表可以從表中任意一個(gè)結(jié)點(diǎn)開始遍歷整個(gè)鏈表。
有時(shí)單鏈表常用操作是在表頭和表尾進(jìn)行的,此時(shí)不設(shè)頭指針而僅設(shè)尾指針。
五、靜態(tài)鏈表
借助數(shù)組來描述線性表的鏈?zhǔn)浇Y(jié)構(gòu),結(jié)點(diǎn)也有數(shù)據(jù)域和指針域。與鏈表的指針不同,靜態(tài)鏈表的指針是結(jié)點(diǎn)的相對地址(數(shù)組下標(biāo)),又稱游標(biāo)。
靜態(tài)鏈表需要預(yù)先分配一塊連續(xù)的內(nèi)存空間。
六、順序表和鏈表的比較
| 存取(讀寫)方式 | 既可以順序存取,也可以隨機(jī)存取 | 只能從表頭順序存取元素 |
| 邏輯結(jié)構(gòu)與物理結(jié)構(gòu) | 邏輯上相鄰的元素,對應(yīng)的物理存儲(chǔ)位置也相鄰 | 邏輯上相鄰的元素,物理存儲(chǔ)位置不一定相鄰,其對應(yīng)的邏輯關(guān)系通過指針鏈接來表示 |
| 按值查找 | 順序表有序時(shí),可采用折半查找,時(shí)間復(fù)雜度為O(log2n)O(log_2n)O(log2?n),若無序,時(shí)間復(fù)雜度為O(n) | 時(shí)間復(fù)雜度為O(n) |
| 按序號查找 | 順序表支持隨機(jī)訪問,時(shí)間復(fù)雜度僅為O(1) | 時(shí)間復(fù)雜度為O(n) |
| 插入、刪除 | 平均需要移動(dòng)半個(gè)表長的元素 | 只需修改相關(guān)結(jié)點(diǎn)的指針域 |
| 空間分配 | 在靜態(tài)存儲(chǔ)分配情形,一旦存儲(chǔ)空間裝滿就不能擴(kuò)充,加入新元素會(huì)導(dǎo)致內(nèi)存溢出,因此需要預(yù)先分配足夠大的空間。但預(yù)先分配過大,會(huì)導(dǎo)致后部空間大量閑置;動(dòng)態(tài)存儲(chǔ)分配雖然存儲(chǔ)空間可以擴(kuò)充,但需要移動(dòng)大量元素,導(dǎo)致操作效率降低,若內(nèi)存沒有更大塊的連續(xù)存儲(chǔ)空間,則會(huì)導(dǎo)致分配失敗。 | 鏈?zhǔn)酱鎯?chǔ)的結(jié)點(diǎn)空間只需在需要是申請,只要內(nèi)存有空間就可以分配,操作靈活、高效。 |
如何選取存儲(chǔ)結(jié)構(gòu):
- 基于存儲(chǔ)考慮:難以估計(jì)線性表的長度或存儲(chǔ)規(guī)模時(shí),不宜采用順序表;鏈表實(shí)現(xiàn)不用估計(jì)存儲(chǔ)規(guī)模,但鏈表的存儲(chǔ)密度較低。
- 基于運(yùn)算考慮:如經(jīng)常做的運(yùn)算時(shí)按序號訪問元素,則順序表優(yōu)于鏈表;如經(jīng)常進(jìn)行插入、刪除操作,鏈表較優(yōu)。
- 基于環(huán)境考慮:任何高級語言都有數(shù)組類型,順序表較容易實(shí)現(xiàn);鏈表的操作是基于指針的。
通常,較穩(wěn)定的線性表選擇順序存儲(chǔ),而頻繁進(jìn)行插入、刪除操作的線性表(動(dòng)態(tài)性強(qiáng))宜選擇鏈?zhǔn)酱鎯?chǔ)。
七、特殊矩陣的壓縮儲(chǔ)存
數(shù)組的定義
數(shù)組是由n(n ≥\ge≥ 1)個(gè)相同類型的數(shù)據(jù)元素構(gòu)成的有序序列。
每個(gè)元素在線性關(guān)系中的序號稱為該元素的下標(biāo),下標(biāo)的取值范圍稱為數(shù)組的維界。
數(shù)組是線性表的推廣:一維數(shù)組可視為一個(gè)線性表,二維數(shù)組可視為其元素也是定長線性表的線性表。
數(shù)組一旦被定義。其維數(shù)和維界就不再改變,因此除初始化和銷毀外,數(shù)組只有存取元素和修改元素的操作。
數(shù)組的存儲(chǔ)結(jié)構(gòu)
對于多維數(shù)組,有按行優(yōu)先和按列優(yōu)先兩種映射方法。
設(shè)二維數(shù)組Ah1×h2A_{h_1\times h_2}Ah1?×h2??的行下標(biāo)和列下標(biāo)范圍分別為[l1,h1],[l2,h2][l_1,h_1],[l_2, h_2][l1?,h1?],[l2?,h2?]。
其按行優(yōu)先存儲(chǔ)時(shí),LOC(ai,j)=LOC(al1,l2)+[(i?l1)×(h2?l2+1)+(j?l2)]×LLOC(a_{i,j})=LOC(a_{l_1,l_2})+[(i-l_1)\times (h_2-l_2+ 1)+(j-l_2)]\times LLOC(ai,j?)=LOC(al1?,l2??)+[(i?l1?)×(h2??l2?+1)+(j?l2?)]×L其按列優(yōu)先存儲(chǔ)時(shí),LOC(ai,j)=LOC(al1,l2)+[(j?l2)×(h1?l1+1)+(i?l1)]×LLOC(a_{i,j})=LOC(a_{l_1,l_2})+[(j-l_2)\times (h_1-l_1+1)+(i-l_1)]\times LLOC(ai,j?)=LOC(al1?,l2??)+[(j?l2?)×(h1??l1?+1)+(i?l1?)]×L
矩陣的壓縮存儲(chǔ)
為多個(gè)值相同的元素只分配一個(gè)存儲(chǔ)空間,對零元素不分配存儲(chǔ)空間,目的是節(jié)省空間。
1. 對稱矩陣
將對稱矩陣A[1…n][1…n]存放在一維數(shù)組B[n(n+1/2)]中,只存放下三角部分的元素。
2. 三角矩陣
下三角矩陣中,上三角區(qū)的所有元素均為同一常量,其儲(chǔ)存思想與對稱矩陣類似,不同之處在于儲(chǔ)存完下三角區(qū)和主對角線上的元素后,在儲(chǔ)存上三角取的常量一次。
943 2019年選擇第9題默認(rèn)矩陣下標(biāo)從0開始
3. 三對稱矩陣(帶狀矩陣)
三對角線上的元素ai,ja_{i,j}ai,j?在一維數(shù)組中的下標(biāo)為k=2+3(i-1)+(j-i+1)-1=2i+j-1(數(shù)組和元素下標(biāo)均從0開始)。
4. 稀疏矩陣
矩陣中非零元素個(gè)數(shù)遠(yuǎn)小于矩陣元素的矩陣。
通常將非零元素及其相應(yīng)的行和列構(gòu)成一個(gè)三元組,然后按照一定規(guī)則儲(chǔ)存這些三元組。
稀疏矩陣壓縮存儲(chǔ)后便失去了隨機(jī)存儲(chǔ)的特性。
八、廣義表
c++中union關(guān)鍵字詳見
廣義表的定義
廣義表的操作
getHead():獲得廣義表的第一個(gè)元素;
getTail():獲得以廣義表出第一個(gè)元素外的其余元素構(gòu)成的廣義表。
如:A=(a), B=(b,c,d),C=(()),那么
getHead(A)=a, getHead(B)=b, getHead(C)=()
getTail(B)=(), getTail(B)=(c,d), getTail(C)=()
總結(jié)
以上是生活随笔為你收集整理的王道408数据结构——第二章 线性表的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 王道408数据结构——第一章 绪论
- 下一篇: 王道408数据结构——第三章 栈和队列