七、線性表的鏈式存儲結構
1、問題引入
開發數組類模板的原因在於:在創建基於順序存儲結構的線性表時,發現這樣的線性表可能被誤用,因為重載了數組訪問操作符,使用時跟數組類似,但是線性表和數組有很大的區別,所以激發了新的需求:開發數組類替換C++原生數組類,因為原生數組類也存在著很大缺陷,使用不方便。
基於順序存儲結構的線性表的另一個缺點:插入或刪除元素時,涉及到大量數據元素的移動,對於效率的影響非常大
一個新的需求:在插入或刪除元素時不需要大量移動數據元素的一種數據結構,即基於鏈式存儲結構的線性表
2、鏈式結構的定義
為了表示每個數據元素於其直接後繼元素之間的邏輯關系;數據元素除了存儲本身的信息外,還需要存儲其直接後繼的信息。
\(a_i\)和\(a_{i+1}\)是線性表中的兩個相鄰數據元素,在物理內存中無相鄰關系。
一個數據元素包含了兩部分:\(a_i\)是數據元素本身的數據信息,還有一個地址信息,地址是第\(i\)個元素的直接後繼,即第\(i+1\)個的元素在內存中的地址信息。換句話說就是如果找到了第\(i\)個元素,不僅可以得到第\(i\)個元素的本身的值之外,還可以得到第\(i+1\)個元素在內存中的位置
3、鏈式存儲邏輯結構
基於鏈式存儲結構的線性表中,每個結點都包含數據域和指針域
- 數據域:存儲數據元素本身
- 指針域:存儲相鄰結點的地址
兩種線性表名稱統一:
- 順序表:基於順序存儲結構的線性表
- 鏈表:基於鏈式存儲結構的線性表
- 單鏈表:每個結點只包含直接後繼的地址信息
- 循環鏈表:單鏈表的最後一個結點的直接後繼為第一個結點
- 雙向鏈表:單鏈表中的結點包含直接前驅和後繼的地址信息
- 雙向循環鏈表......
4、鏈表中的基本概念
- 頭結點:鏈表中的輔助結點,包含指向第一個數據元素的指針;不包含任何數據信息,是為了簡化代碼進行輔助
- 數據結點:鏈表中代表數據元素的結點,表現形式為:(數據元素,地址)
- 尾結點:鏈表中的最後一個數據結點。單獨放出的原因:尾結點包含的地址信息直接決定了鏈表的性質,地址信息為空,就是單鏈表;地址為第0個元素的地址信息,就是循環鏈表;地址信息為隨機值,就是一個非法鏈表
5、單鏈表
5.1 單鏈表中的結點定義
// 用struct定義類,默認屬性是public // T是泛指類型,鏈表可以存儲各種類型的數據 struct Node : public Object { T value; Node* next; // 指向後繼結點的指針 }
5.2 單鏈表的內部結構
頭結點在單鏈表中的意義是:輔助數據元素的定位,方便插入和刪除操作,因此,頭結點不存儲實際的數據元素。
5.3 在目標位置處插入數據元素
從頭結點開始,通過
current
指針定位到目標位置從堆空間申請新的Node結點
執行操作
node->value = e; node->next = current->next; current->next - node;
5.4 在目標位置刪除數據元素
從頭結點開始,通過
previous
指針定位到目標位置的前一個地址使用
toDel
指針指向需要刪除的結點執行操作:
toDel = previous->next; previous->next = toDel->next; delete toDel;
6、小結
鏈表中的數據元素在物理內存中無相鄰關系
鏈表中的結點都包含數據域和指針域
頭結點用於輔助數據元素定位,方便插入和刪除操作
插入和刪除操作需要保證鏈表的完整性
七、線性表的鏈式存儲結構