1. 程式人生 > >七、線性表的鏈式存儲結構

七、線性表的鏈式存儲結構

順序存儲結構 雙向鏈表 obj 包含 循環鏈表 雙向循環鏈表 和數 ext let

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 在目標位置處插入數據元素

  1. 從頭結點開始,通過current指針定位到目標位置

  2. 從堆空間申請新的Node結點

  3. 執行操作

    node->value = e;
    node->next = current->next;
    current->next - node;

5.4 在目標位置刪除數據元素

  1. 從頭結點開始,通過previous指針定位到目標位置的前一個地址

  2. 使用toDel指針指向需要刪除的結點

  3. 執行操作:

    toDel = previous->next;
    previous->next = toDel->next;
    delete toDel;

6、小結

鏈表中的數據元素在物理內存中無相鄰關系

鏈表中的結點都包含數據域和指針域

頭結點用於輔助數據元素定位,方便插入和刪除操作

插入和刪除操作需要保證鏈表的完整性

七、線性表的鏈式存儲結構