github:代碼實現
本文算法均使用python3實現
1. 二叉樹
1.1 二叉樹的定義
二叉樹是一種特殊的樹,它具有以下特點:
(1)樹中每個節點最多只能有兩棵樹,即每個節點的度最多為2。
(2)二叉樹的子樹有左右之分,即左子樹與右子樹,次序不能顛倒。
(3)二叉樹即使只有一個子樹時,也要區分是左子樹還是右子樹。
1.2 滿二叉樹
滿二叉樹作為一種特殊的二叉樹,它是指:所有的分支節點都存在左子樹與右子樹,並且所有的葉子節點都在同一層上。其特點有:
(1)葉子節點只能出現在最下面一層
(2)非葉子節點度一定是2
(3)在同樣深度的二叉樹中,滿二叉樹的節點個數最多,節點個數為: $ 2^h -1 $ ,其中 $ h $ 為樹的深度。
1.3 完全二叉樹
若設二叉樹的深度為 $ h $ ,除第 $ h $ 層外,其它各層 $ (1~h-1) $ 的結點數都達到最大個數,第 $ h $ 層所有的結點都連續集中在最左邊,這就是完全二叉樹。其具有以下特點:
(1)葉子節點可以出現在最后一層或倒數第二層。
(2)最后一層的葉子節點一定集中在左部連續位置。
(3)完全二叉樹嚴格按層序編號。(可利用數組或列表進行實現,滿二叉樹同)
(4)若一個節點為葉子節點,那么編號比其大的節點均為葉子節點。
2. 二叉樹的相關性質
2.1 二叉樹性質
(1)在非空二叉樹的 $ i $ 層上,至多有 $ 2^{i-1} $ 個節點 $ (i \geq 1) $ 。
(2)在深度為 $ h $ 的二叉樹上最多有 $ 2^h -1 $ 個節點 $(k \geq 1) $ 。
(3)對於任何一棵非空的二叉樹,如果葉節點個數為 $ n_0 $ ,度數為 $ 2 $ 的節點個數為 $ n_2 $ ,則有: $ n_0 = n_2 + 1 $ 。
2.1 完全二叉樹性質
(1)具有 $ n $ 個的結點的完全二叉樹的深度為 $ \log_2{n+1} $ 。.
(2)如果有一顆有 $ n $ 個節點的完全二叉樹的節點按層次序編號,對任一層的節點 $ i ,(1 \geq i \geq n)$ 有:
(2.1)如果 $ i=1 $ ,則節點是二叉樹的根,無雙親,如果 $ i>1 $ ,則其雙親節點為 $ \lfloor i/2 \rfloor $ 。
(2.2)如果 $ 2i>n $ 那么節點i沒有左孩子,否則其左孩子為 $ 2i $ 。
(2.3)如果 $ 2i+1>n $ 那么節點沒有右孩子,否則右孩子為 $ 2i+1 $ 。
3. 二叉樹的遍歷
以下遍歷以該二叉樹為例:
3.1 前序遍歷
思想:先訪問根節點,再先序遍歷左子樹,然后再先序遍歷右子樹。總的來說是根—左—右
上圖先序遍歷結果為為:$ 1,2,4,8,9,5,3,6,7 $
代碼如下:
def PreOrder(self, root):
'''打印二叉樹(先序)'''
if root == None:
return
print(root.val, end=' ')
self.PreOrder(root.left)
self.PreOrder(root.right)
3.2 中序遍歷
思想:先中序訪問左子樹,然后訪問根,最后中序訪問右子樹。總的來說是左—根—右
上圖中序遍歷結果為為:$ 8,4,9,2,5,1,6,3,7 $
代碼如下:
def InOrder(self, root):
'''中序打印'''
if root == None:
return
self.InOrder(root.left)
print(root.val, end=' ')
self.InOrder(root.right)
3.3 后序遍歷
思想:先后序訪問左子樹,然后后序訪問右子樹,最后訪問根。總的來說是左—右—根
上圖后序遍歷結果為為:$ 8,9,4,5,2,6,7,3,1 $
代碼如下:
def BacOrder(self, root):
'''后序打印'''
if root == None:
return
self.BacOrder(root.left)
self.BacOrder(root.right)
print(root.val, end=' ')
3.4 層次遍歷(寬度優先遍歷)
思想:利用隊列,依次將根,左子樹,右子樹存入隊列,按照隊列的先進先出規則來實現層次遍歷。
上圖后序遍歷結果為為:$ 1,2,3,4,5,6,7,8,9 $
代碼如下:
def BFS(self, root):
'''廣度優先'''
if root == None:
return
# queue隊列,保存節點
queue = []
# res保存節點值,作為結果
#vals = []
queue.append(root)
while queue:
# 拿出隊首節點
currentNode = queue.pop(0)
#vals.append(currentNode.val)
print(currentNode.val, end=' ')
if currentNode.left:
queue.append(currentNode.left)
if currentNode.right:
queue.append(currentNode.right)
#return vals
3.5 深度優先遍歷
思想:利用棧,先將根入棧,再將根出棧,並將根的右子樹,左子樹存入棧,按照棧的先進后出規則來實現深度優先遍歷。
上圖后序遍歷結果為為:$ 1,2,4,8,9,5,3,6,7 $
代碼如下:
def DFS(self, root):
'''深度優先'''
if root == None:
return
# 棧用來保存未訪問節點
stack = []
# vals保存節點值,作為結果
#vals = []
stack.append(root)
while stack:
# 拿出棧頂節點
currentNode = stack.pop()
#vals.append(currentNode.val)
print(currentNode.val, end=' ')
if currentNode.right:
stack.append(currentNode.right)
if currentNode.left:
stack.append(currentNode.left)
#return vals
3.6 代碼運行結果
引用及參考:
[1]《數據結構》李春葆著
[2] http://www.cnblogs.com/polly333/p/4740355.html
寫在最后:本文參考以上資料進行整合與總結,屬於原創,文章中可能出現理解不當的地方,若有所見解或異議可在下方評論,謝謝!
若需轉載請注明:https://www.cnblogs.com/lliuye/p/9143676.html
