2.二叉樹-基本概念

二叉樹
高度:根節點的高度最高(從0開始算起)
深度:根節點的深度最淺(從0開始算起)
層:根節點的層數最小(從1開始算起)
在這裏插入圖片描述
二叉樹中有兩種比較特殊的二叉樹:

完全二叉樹:葉子節點都在最底下兩層,最後一層的葉子節點都靠左排列,並且除了最後一層,其他層的節點個數都要達到最大
滿二叉樹:葉子節點全都在最底層,除了葉子節點之外,每個節點都有左右兩 個子節點

二叉樹的存儲最直觀的是鏈式存儲法:

class Node{
	int data;
	Node left;
	Node right;
}

在這裏插入圖片描述
基於數組的順序存儲法:
我們把根節點存儲在下標 i = 1 的位置,那左子節點存儲在下標 2 * i = 2 的位置,右子節點存儲在 2 * i + 1 = 3 的位置。以此類推,B 節點的左子節點存儲在 2 * i = 2 * 2 = 4 的位置,右子節點存儲在 2 * i + 1 = 2 * 2 + 1 = 5。根節點一般不存在下標爲0的位置,因爲這樣的話,左節點就是i2+1,右子節點存儲在i2+2的位置,計算的時候不方便計算,左右子樹都有一個加法。
在這裏插入圖片描述
基於數組的順序存儲方法存儲非完全二叉式的時候會浪費很多空間。這也是爲什麼完全
二叉樹會單獨拎出來的原因,也是爲什麼完全二叉樹要求最後一層的子節點都靠左的原因。

二叉樹的前、中、後序,表示的是節點與它的左右子樹節點遍歷打印的先後順序(根節點的打印時機)。
前序遍歷是指,對於樹中的任意節點來說,先打印這個節點,然後再打印它的左子樹,最後
打印它的右子樹。
中序遍歷是指,對於樹中的任意節點來說,先打印它的左子樹,然後再打印它本身,最後打
印它的右子樹。
後序遍歷是指,對於樹中的任意節點來說,先打印它的左子樹,然後再打印它的右子樹,最
後打印這個節點本身。
在這裏插入圖片描述
實際上,二叉樹的前、中、後序遍歷就是一個遞歸的過程。比如,前序遍歷,其實就是先打印根
節點,然後再遞歸地打印左子樹,最後遞歸地打印右子樹。
寫遞歸代碼的關鍵,就是看能不能寫出遞推公式,而寫遞推公式的關鍵就是,如果要解決問題
A,就假設子問題 B、C 已經解決,然後再來看如何利用 B、C 來解決 A。所以,我們可以把
前、中、後序遍歷的遞推公式都寫出來。

preOrder(Tree)=print(data)->preOrder(Tree.left)->preOrder(Tree.right)
inOrder(Tree)=inOrder(Tree.left)->print(data)->inOrder(Tree.right)
postOrder(Tree)=postOrder(Tree.left)->postOrder(Tree.right)->print(data)

從前面畫的前、中、後序遍歷的順序圖,可以看出來,每個節點最多會被訪問兩次,所以遍歷
操作的時間複雜度,跟節點的個數 n 成正比,也就是說二叉樹遍歷的時間複雜度是 O(n)。

特殊的二叉樹

特殊的的二叉樹,二叉查找樹。二叉查找樹最大的特點就是,支持動態數據集合的快速插入、刪除、查找操作。
極端情況下二叉樹會退化成爲鏈表。
所以說又出現了平衡二叉查找樹。

平衡二叉樹的嚴格定義是:二叉樹中的任何一個節點的左右子樹的高度相差不能大於1

所以說完全二叉樹一定是平衡二叉樹,非完全二叉樹也有可能是平衡樹。
在這裏插入圖片描述

再加上查找二字則是:在樹中的任意一個節點,其左子樹中的每個節點的值,都要小於這個節點的值,而右子樹節點的值都大於這個節點的值

平衡二叉查找樹的數據結構實現有很多種,如:

  • AVL樹
  • 紅黑樹(不滿足上面的平衡二叉樹的絕對定義)
  • 伸展樹(Splay Tree),樹堆(Treap)等等。

由此又延展出了平衡多叉查找樹數據結構,如:

  • B樹(B-樹)
  • B+樹
  • B*樹(B+樹的變種)

二叉樹增加,刪除,刪除的複雜度是的O(log n)
散列表增加,刪除,刪除的複雜度是的O(1)

但是散列表的底層是數組存儲的數據,所以涉及到擴容,縮容並不方便
在加上散列函數的設計,衝突解決辦法等,要考慮的東西很多。如果考慮上散列衝突,這個O(1)並不比常量小。再加上hash函數的耗時,效率並不一定很高。另外散列表中的數據是無序的,所以排列輸出比較不方便。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章