資料結構與演算法(1)

輕藍雨發表於2020-12-07

資料結構

資料結構指的是資料的組織、管理和儲存格式,可以高效地訪問和修改資料。常見的資料結構如下表:

型別舉例
線性結構陣列、連結串列、棧、佇列、雜湊表
二叉樹、二叉堆……
單向圖、雙向圖……
其他跳錶、雜湊連結串列、點陣圖……

陣列 array

陣列:在記憶體上連續的順序儲存,訪問效率高,不便於插入、刪除和擴充套件。array比較適用於讀操作多、寫操作少的場景。

/****************************************
*
* typename array[] = {};
*  _________________________________________________________
* |array[0] | array[1] | array[2] | array[3] | ... |
*  ---------------------------------------------------------
*
*/

連結串列 linked list

物理上不連續、非順序的儲存的結構,由一個一個相連的節點(包含資料、指標)組成。節點的指標(next)指向其後繼節點。

/**************************************************************
*
*      _________    -->  ________    -->  ________
*     |   data  |   |   |  data  |   |   |  data  |
*     |---------    |   |--------|   |   |--------|
*     |   next  |---|   |  next  |---|   |  NULL  |
*      ---------         --------         --------
*
*/

雙向連結串列 doubly linked list

雙向連結串列的節點包含兩個指標(prev:指向前驅節點的指標,next:指向後繼節點的指標)

棧 stack

棧:一種先進後出(First In Last Out, FILO),看上去像一個桶的線性結構。
stack
棧即可以用陣列來實現,也可以用連結串列來實現。棧頂(top)先出棧,棧底(bottom)後出棧。

佇列 queue

佇列:就像去食堂排隊打飯一樣的先進先出(First In First Out, FIFO)的線性資料結構。隊頭(front)先出隊,隊尾(rear)後出隊。
queue
上圖右側是表示一個迴圈佇列,使用陣列即可以很方便的表示。

雜湊表 hash table(雜湊表)

hash table

樹 tree

樹,多個節點的集合,包含以下特性:

  • 有且僅有一個節點稱為根(root)節點
  • 每個節點又可以包含多個子節點,沒有子節點的節點稱為葉子(leaf)節點
  • 任意一個節點只能是某一個節點(稱為父節點(parent))的子節點,即樹支只能分叉,不能生長到一起;即任意節點只能有一個父節點
  • 從根節點(root)開始,到最後一批葉子節點(leaf)的代數,稱為樹的深度或高度或層數(h)
  • 同級或同一代或同一層的所有節點互相稱為兄弟節點(sibling)

整個樹有點像一個家譜圖。有父親parent,孩子child,兄弟sibling等節點關係。

二叉樹

binary tree

二叉樹的儲存

鏈式儲存
陣列儲存
鏈式儲存二叉樹,直觀形象,程式碼簡單,需要動態申請記憶體來儲存節點;
使用陣列來儲存二叉樹,訪問效率高,但儲存稀疏的二叉樹則非常浪費儲存空間。

二叉查詢樹(二叉排序樹)binary search tree

二叉查詢樹:左子樹所有節點均小於根節點的值;右子樹所有節點均大於樹節點的值;且左、右子樹均是二叉查詢樹。
binary search tree

二叉樹的自平衡

二叉樹新增節點的插入需要根據新插入的節點調整整個二叉樹以保證二叉樹維護相對的平衡而不會變成一條線性的連結串列。

二叉樹的遍歷

  • 深度優先遍歷(DFS):前序遍歷、中序遍歷、後序遍歷
  • 廣度優先遍歷(BFS):層序遍歷

前序遍歷

root—>left sub tree —> right sub tree

中序遍歷

left sub tree —> root —> right sub tree

後序遍歷

left sub tree —> right sub tree —> root

以上三種遍歷均使用遞迴來實現,則只在詞句順序上有區別;使用遞迴來實現也可以改為使用stack來實現。

層序遍歷

藉助佇列,逐層入隊出隊,出隊時出隊節點的子節點按序入隊,佇列為空,則樹遍歷結束。

二叉堆

二叉堆,一種具有自平衡能力的完全二叉樹。
最大堆:
∀ p a r e n t , p a r e n t > = l e f t c h i l d , p a r e n t > = r i g h t c h i l d \forall parent, parent >= left child, parent >= right child parent,parent>=leftchild,parent>=rightchild
最小堆:
∀ p a r e n t , p a r e n t < = l e f t c h i l d , p a r e n t < = r i g h t c h i l d \forall parent, parent <= left child, parent <= right child parent,parent<=leftchild,parent<=rightchild

二叉堆的自我調整

二叉堆在構建、插入節點、刪除節點的時候都需要調整節點的順序。

比如,在最小堆中,插入新的節點,可以從最後的位置,將新插入的節點與其父節點比較,只要比父節點小,則將其與父節點交換。依次直到“上浮”到能到的最“頂端”的位置。

同樣的,在最小堆中,要刪除一個節點,則將最後的節點放到刪除節點的位置,再依次“下沉”到最“底端”的位置。

要構建一棵二叉堆,則將所有非葉子節點依次“下沉”。

插入、刪除二叉堆中的一個節點的時間複雜度均為 O ( l o g n ) O(log n) O(logn),構建二叉堆的時間複雜度為 O ( n ) O(n) O(n)

二叉堆使用陣列(而不是連結串列)來儲存更為簡單。

優先佇列

最大優先佇列,無論入隊順序如何,都是最大元素先出隊。

最小優先佇列,無論入隊順序如何,都是最小元素先出隊。

使用二叉堆來實現優先佇列,入隊即插入新節點,出隊即刪除堆頂節點,時間複雜度均為 O ( l o g n ) O(log n) O(logn)

資料儲存的物理結構與邏輯結構

邏輯結構線性結構(順序表、棧、佇列)非線性結構(樹、圖)
物理結構順序儲存(陣列)鏈式儲存(連結串列)

演算法

演算法,主要考慮的時間複雜度(基本操作的執行次數)和空間複雜度(演算法所佔用儲存空間的規模)。

一般用大 O O O表示法來表示。常見的量級比較:
O ( 1 ) < O ( l o g n ) < O ( n ) < O ( n l o g n ) < O ( n 2 ) O(1) < O(log n) < O(n) < O(n log n) < O(n^2) O(1)<O(logn)<O(n)<O(nlogn)<O(n2)

我們將在下一篇中開始複習相關的演算法。

相關文章