《大話資料結構》之線性表

2021-10-04 17:39:45 字數 4895 閱讀 8726

自己在看《大話資料結構》這本書,順便需要練習使用部落格,就順便把自己的讀書筆記發上來啦。

線性表(list):零個或多個(相同型別的)資料元素的有限序列。

順序儲存定義

線性表的順序儲存結構,指的是用一段位址連續的儲存單元依次儲存線性表的資料元素。

順序儲存方式

線性表的順序儲存結構就是在記憶體中找了塊地兒,通過佔位的形式,把一定的記憶體空間給佔了,然後把相同資料型別的資料元素依次存放在這塊空地中。

既然線性表的每個資料元素的型別都相同,所以可以用(高階程式語言中的)一維陣列來實現順序儲存結構,即把第乙個資料元素存到陣列下標為0的位置中,接著把線性表相鄰的元素儲存在陣列中相鄰的位置。

描述順序儲存結構需要三個屬性:

儲存空間的起始位置:陣列的儲存位置就是儲存空間的儲存位置。

線性表的最大儲存容量:陣列長度。

線性表的當前長度。

陣列長度和線性表長度區別

陣列的長度是存放線性表的儲存空間的長度,儲存分配後這個量一般是不變的。

線性表的長度是線性表中資料元素的個數,隨著線性表插入和刪除操作的進行,這個量是變化的。

在任意時刻,線性表長度應該小於等於陣列長度。

位址計算方法

線性表的起始是1。

線性表的第 i 個元素是要儲存在陣列下標為 i-1 的位置。

用陣列儲存順序表意味著要分配固定長度的陣列空間,由於線性表中可以進行插入和刪除操作,因此分配的陣列空間要大於等於當前線性表的長度。

記憶體中的位址都是有編號的。儲存器中的每個儲存單元都有自己的編號,這個編號稱為位址。

每個資料元素,占用c個儲存單元,loc表示獲得儲存位置的函式。

所以第 i 個資料元素 ai 的儲存位置可以由 a1 推算得出:

loc(ai)=loc(a1) + (i-1)*c

通過這個公式,可以隨時算出線性表中任意位置的位址,不管它是第乙個還是最後乙個,都是相同的時間。那麼我們對每個線性表位置的存入或者取出資料,對於計算機來說,都是相等的時間,也就是乙個常數,用時間複雜度來說,它的訪問時間效能為o(1)。我們通常把具有這一特點的儲存結構稱為隨機儲存結構。

插入和刪除的時間複雜度

最好的情況,插入到最後乙個位置或者刪除最後乙個元素,此時時間複雜度為o(1),因為不需要移動元素。

最壞的情況,元素要插入到第乙個位置或者刪除第乙個元素,此時時間複雜度為o(n),因為所有的元素向後或者向前。

平均的情況,元素插入到第i個位置,或者刪除第i個元素,需要移動 n-i 個元素。根據概率原理,每個位置插入或刪除元素的可能性是相同的,也就是說,位置靠前,移動元素多,位置靠後,移動元素少。最終平均移動次數和最中間的那個元素的移動次數相等,為(n - 1)/2。所以平均時間複雜度還是o(n)。

線性表的順序儲存結構,在存、讀資料時,不管是哪個位置,時間複雜度都是o(1);而插入或刪除時,時間複雜度都是o(n)。

線性表順序儲存結構的優缺點

-優點

-缺點順序儲存結構最大的缺點就是插入和刪除時需要移動大量的元素,耗費時間。

線性表鏈式儲存結構定義

線性表的鏈式儲存結構的特點是用一組任意的儲存單元儲存線性表資料元素,這組儲存單元可以是連續的,也可以是不連續的。即這些資料元素可以存在記憶體未被占用的任意位置。

把儲存資料元素資訊的域稱為資料域,把儲存直接後繼位置的域稱為指標域。指標域中儲存的資訊稱做指標或者鏈。這兩部分組成資料元素ai的儲存映像,稱為結點(node)。

**n個結點鏈結成乙個鍊錶,即為線性表的鏈式儲存結構,因為此鍊錶的每個結點中只包含乙個指標域,所以叫做單鏈表。**單鏈表正是通過每個結點的指標域將線性表的資料元素按其邏輯次序鏈結在一起。

**鍊錶中第乙個結點的儲存位置叫做頭指標。**整個鍊錶的訪問必須從頭指標開始。之後的每乙個結點,其實就是上乙個的後繼指標指向的位置。線性鍊錶的最後乙個結點指標為「空」。

**在單鏈表的第乙個結點前附設乙個結點,稱為頭結點。**頭結點的資料域可以不儲存任何資訊,頭結點的指標域儲存指向第乙個元素結點的指標。

頭指標和頭結點異同

頭指標

頭結點

若線性表為空表,則頭結點的指標域為「空」

-獲得鍊錶第 i 個資料的演算法思路:

1. 宣告乙個結點 p 指向鍊錶第乙個結點,初始化 j 從1開始;

2. 當 j < i 時,就遍歷鍊錶,讓 p的指標向後移動,不斷指向下乙個結點,j 累加1;

3. 若到鍊錶末尾 p為空,則說明第 i 個元素不存在;

4. 否則查詢成功,返回結點 p 的資料。

最壞的時間複雜度為o(n)。

單鏈表結構中沒有定義表長,不知道要迴圈多少次,不方便用 for 控制迴圈。其主要核心思想是工作指標後移

單鏈表的插入

-單鏈表第 i 個結點插入結點的演算法思路:

宣告一結點 p 指向鍊錶第乙個結點,初始化 j 從1開始;

當 j < i 時,就遍歷鍊錶,讓p的指標向後移動,不斷指向下乙個結點,j 累加1;

若到鍊錶末尾 p 為空,則說明第 i 個元素不存在;

否則查詢成功,在系統中生成乙個空結點s;

將資料元素 e 賦值給 s->data;

單鏈表的插入標準語句 s->next = p->next; p->next = s;

返回成功。

單鏈表的刪除

-單鏈表第 i 個資料刪除結點的演算法思路:

宣告一結點 p 指向鍊錶第乙個結點,初始化 j 從1開始;

當 j < i 時,就遍歷鍊錶,讓p的指標向後移動,不斷指向下乙個結點,j 累加1;

若到鍊錶末尾 p 為空,則說明第 i 個元素不存在;

否則查詢成功,將欲刪除的結點 p->next 賦值給q;

單鏈表的刪除標準語句 p->next = q->next;

將 q 結點中的資料賦值給 e,作為返回;

釋放 q 結點;

返回成功。

單鏈表的插入和刪除演算法,都是由兩部分組成:1. 遍歷查詢第 i 個元素; 2. 插入和刪除元素。

時間複雜度都是o(n)

第一步,找到第 i 個位置的指標,此時是o(n),接下來只是簡單地通過賦值移動指標,時間複雜度都是o(1)。

回顧一下順序儲存結構的建立,其實就是乙個陣列的初始化,即宣告乙個型別和大小的陣列並賦值的過程。而單鏈表是一種動態結構,對於每個鍊錶來說,它所占用空間的大小和位置是不需要預先分配劃定的,可以根據系統的情況和實際的需求即時生成。

所以建立單鏈表的過程就是乙個動態生成鍊錶的過程。即從「空表」的初始狀態起,依次建立各元素結點,並逐個插入鍊錶。

單鏈表整表建立的演算法思路:

宣告一結點 p 和計數器變數 i ;

初始化一空鍊錶 l;

讓 l 的頭結點的指標指向 null,即建立乙個帶頭結點的空鍊錶;

迴圈:

使用的是插隊的方法,就是始終讓新結點在第一的位置。這種方法稱為頭插法。

還可以每次都把新結點都插在終端結點的後面,這種演算法稱為尾插法。

...

r->next = p;

r = p;

//將p結點這個最後的結點賦值給r,此時r又是最終的尾結點了

其中,r是指向尾結點的變數,r會隨著迴圈不斷地變換結點。

迴圈結束後

r->next = null;
演算法思路如下:

宣告一結點 p 和 q;

將第乙個結點賦值給 p;

迴圈:

不使用指標如何處理鍊錶結構的靜態鍊錶方法。

對於單鏈表,由於每個結點只儲存了向後的指標,到了尾標誌就停止了向後鏈的操作,這樣,當中某一結點就無法找到它的前驅結點了。

** 將單鏈表中終端結點的指標端由空指標改為指向頭結點,就使整個單鏈表形成了乙個環,這種頭尾相接的單鏈表稱為單迴圈鍊錶,簡稱迴圈鍊錶。**

迴圈鍊錶解決了乙個,如何從當中乙個結點出發,訪問到鍊錶的全部結點的問題。

為了使空鍊錶與非空煉表處理一致,我們通常設乙個頭結點。

在迴圈鍊錶中,不用頭指標,而是用指向終端結點的尾指標來表示迴圈鍊錶,方便查詢開始結點(rear->next->next)和終端結點(rear),時間複雜度都是o(1)。

有了尾指標,可以很方便的將兩個迴圈鍊錶合為乙個鍊錶。

在單鏈表中,有了next指標,這就使得我們要查詢下一結點的時間複雜度為o(1),可是如果要查詢上一結點的話,最壞的時間複雜度就是o(n),因為每次都要從頭開始遍歷查詢。

為了克服單向性這一缺點,設計出了雙向鍊錶。雙向鍊錶是在單鏈表的每個結點中,再設定乙個指向其前驅結點的指標域。

雙向鍊錶也可以是迴圈鍊錶。

p->next->prior = p = p->prior->next

雙向鍊錶的求長度操作、查詢元素操作和獲得元素位置的操作與單鏈表相同。

但雙向鍊錶比單鏈表多了如可以反向遍歷查詢等資料結構,那麼而需要付出一點小小的代價:在插入和刪除時,需要更改兩個指標的變數。

插入將 s 結點插入 p 結點與 p->next 結點之間,

s -> prior = p;

s->next = p->next;

p->next->prior = s;

p->next = s;

順序是先搞定 s 的前驅和後繼,再搞定後結點的前驅,最後解決前結點的後繼。

刪除刪除 p 結點

p->prior->next = p->next;

p->next->prior = p->prior;

free(p);

雙向鍊錶由於每個結點都需要記錄兩份指標,所以在空間上是要占用略多一些。不過由於良好的對稱性,使得對某個結點的前後結點的操作,帶來了方便,可以有效提高演算法的時間效能。即用空間換時間。

《大話資料結構》 線性表

created by pengxiangzhou on 2021 1 24.include ifndef c ds linear list h define c ds linear list h endif c ds linear list h 線性表 順序儲存結構 順序儲存結構的三個屬性 陣列da...

大話資料結構 線性表

線性表是零個或多個資料元素的有限序列。線性表的抽象資料型別定義如下 adt 線性表 list data 線性表的資料物件集合為,每個元素的型別均為datatype。其中,除第乙個元素a1外,每乙個元素有且只有乙個直接前驅元素,除了最後乙個元素an外,每乙個元素有且只有乙個直接後繼元素。資料元素之間的...

讀大話資料結構之線性表

第三章 線性表3.1 線性表的定義 線性表 零個或多個資料元素的有限序列。說明 線性表是乙個序列。也就是說,元素之間是有順序的,若元素存在多個,則第乙個元素無前驅,最後乙個元素無後繼,其他每個元素都有且只有乙個前驅和後繼。線性表強調是有序的。3.2 線性表的順序儲存結構 3.2.1 順序儲存定義 線...