第二章:線性表(順序表VS鏈表)
在 學習數據結構–第二章:線性表(順序存儲、插入、刪除)
和
學習數據結構–第二章:線性表(鏈式存儲、單鏈表、雙鏈表、循環鏈表) 這兩篇文章中分別講了順序表和鏈表的存儲特點以及基本的操作,下面講解順序表和鏈表的一些區別和在解決實際問題的時候我們應該做出怎樣的選擇,以及線性表的常用操作。
1.順序表和鏈表的差異性
在單鏈表中每一個數據的存儲不一定是連續的,所以我們無法實現隨機存取,只能通過指針連接各個結點,所以我們只能實現順序存取。
而在順序表中每一個數據源的存放是連續的,我們只需要通過LOC(A)+(n-1)*sizeof(ElemType)這個式子,只要我們知道第一個元素的地址,我們就可以通過計算得到每一個元素的地址,這樣就可以實現隨機存取和順序存取。故:
單鏈表:只能實現順序存取
。
順序表:可以實現順序存儲
和隨機存取
。
2.邏輯結構和物理結構差異性
單鏈表中數據元素的存儲位置是任意的,可能相鄰也可能不相鄰,而順序表元素的存儲位置一定是相鄰的。
鏈表是通過指向下一個元素的指針來維持邏輯結構的,每一個元素不僅存放了數據元素還存放了下一個數據元素的地址,通過指針將所有的元素穿成一個鏈。而順序表是通過數據元素的相鄰性來維持邏輯結構的,在邏輯上相鄰的數據元素,在物理上也是相鄰的。
順序表:邏輯相鄰物理上也相鄰
,通過相鄰
表示邏輯關機。
單鏈表:邏輯相鄰物理上不一定相鄰
,通過指針
表示邏輯關係。
3.線性表的基本操作
3.1插入
順序表中:元素向後移動->將新元素賦值
單鏈表中:新結點S的next指針指向p結點的後一個結點->修改p結點的next指針指向新的結點S。
3.2刪除
順序表中:將要刪除的元素開始,將後面的元素依次向前移動。
單鏈表中:首先一個新的指針指向將要刪除的結點q—>接着修改q的前面一個結點的next指針指向q後面的的結點—>接着釋放q結點的空間。
插入&刪除
- 單鏈表爲
O(1)
(節點指針已知);O(n)
(節點指針未知),但操作時只需修改指針 - 順序表爲
O(n)且需要大量移動元素
3.3查找
按值查找
順序表中:遍歷整個順序表對比值。O(n)
單鏈表中:遍歷整個單鏈表對比值。O(n)
按序號查找
順序表中:按照序號,我們通過數組的下標既可以直接找到對應序號的數組元素的位置。O(1)
單鏈表中:需要遍歷整個鏈表。O(n)
查找
- 按值查找中單鏈表和順序表(
無序
)都爲O(n); - 按序查找中單鏈表爲O(n),順序表爲O(1);
3.內存空間的差異性
順序存儲 無論靜態分配還是非靜態都需要預先分配
合適的內存空間靜態分配時預分配空間太大回造成浪費,太小會造成溢出;動態分配時雖不會溢出但是擴充需要大量移動元素,操作效率低
鏈式存儲 在需要時分配
結點空間即可,高效方便,但指針要使用額外空間。
4.怎樣選擇線性表的存儲結構?
5.線性表的常用操作
5.1求最值
順序表
首先使用兩個變量標記數組的第一個元素爲最大值和最小值,接着遍歷順序表,如果該元素大於最大值,則修改最大值的變量,如果小於最小值,則修改最小值變量。遍歷結束即可得到最大值和最小值。
時間複雜度:O(n)
int min=L[0];
int max=L[0];
for(int i=0;i<n;i++){
if(min>L[i]){
min=L[i];
}
if(max<L[i]){
max=L[i];
}
}
單鏈表
同理和順序表。
時間複雜度:O(n)
5.2求逆置
順序表
思路一,我們申請一個輔助空間,然後從尾部到頭遍歷整個順序表,然後將每一個元素插入到新的空間中即可,但是這樣的時間和空間複雜度是O(n)。下面講解另一種方法:
我們可以使用兩個標記分別指向頭部元素i
和尾部元素j
的值,接着交換兩個標記的數據元素的值,然後將i
標記向後移動一位,j
標記向前移動一位,繼續交換元素的值…直到i<j
的時候結束。這種方法的時間複雜度爲O(n),空間複雜度爲O(1)
單鏈表
在單鏈表中我們有一個頭指針(p
)和尾指針(r
),我們將第一個數據元素結點移動到(r)
指針後面,接着繼續將第一個數據元素結點移動到(r
)指針後面…持續操作,直到p
指針的下一個結點爲(r
)結點結束。
代碼講解:
p->next!=r
就是移動結束的判斷條件,移動到r
結點作爲第一個結點的時候結束。temp=p->next
是保存p
結點的下一個結點。p->next=temp->next
就是直接將p結點和temp後面的結點相連接
。【前兩個語句是將要移動的結點拿出去並保存】temp->next=r->next
修改要插入的結點的next指針指向r
結點的後一個結點,r->next=temp;
就是連接起來。【後兩個語句是連接操作】
時間複雜度:O(n).
5.3合併
順序表
需要新申請一個空間,大小爲兩個順序表空間的和,然後需要找到兩個書順序表中元素值最小的那個,然後插入的新的表中。這時需要藉助三個標記,一個(i
)指向L1的第一個位置,一個(j
)指向L2的第一個位置,一個(k
)指向新數組,注意這裏的順序表的元素都是從小到大排列的,我們只需要保證合併後的元素值也是從小到大排列。
然後我們需要一次比較兩個數組的元素的值,如果L1[i]<L2[i],這時將L1[i]添加到新的的數組中,同時標記k++,然後讓i++,j不變,然後繼續比較,如果L1數組的元素比較完了,此時L2數組還有剩餘,此時不需要比較了,直接將L2數組元素依次添加到新數組中即可。
其中
i<L1_Size&&j<L2_Size
就是判斷兩個數組是否全部移除。下面的兩個while
判斷就是判斷兩個數組是否全部移除完畢,因爲不知道那個數組沒移除完畢。
時間複雜度:O(n)
單鏈表
基本同理順序表。