一、二叉樹
1.1 二叉樹的定義:
二叉樹是一種特殊的樹,它具有以下特點:
(1)樹中每個節點最多只能有兩棵樹,即每個節點的度最多為2。
(2)二叉樹的子樹有左右之分,即左子樹與右子樹,次序不能顛倒。
(3)二叉樹即使只有一個子樹時,也要區分是左子樹還是右子樹。
1.2 滿二叉樹:
滿二叉樹作為一種特殊的二叉樹,它是指:所有的分支節點都存在左子樹與右子樹,並且所有的葉子節點都在同一層上。其特點有:
(1)葉子節點只能出現在最下面一層
(2)非葉子節點度一定是2
(3)在同樣深度的二叉樹中,滿二叉樹的節點個數最多,節點個數為: 2h−12h−1 ,其中 hh 為樹的深度。
1.3 完全二叉樹:
若設二叉樹的深度為 hh ,除第 hh 層外,其它各層 (1~h−1)(1~h−1) 的結點數都達到最大個數,第 hh 層所有的結點都連續集中在最左邊,這就是完全二叉樹。其具有以下特點:
(1)葉子節點可以出現在最后一層或倒數第二層。
(2)最后一層的葉子節點一定集中在左部連續位置。
(3)完全二叉樹嚴格按層序編號。(可利用數組或列表進行實現,滿二叉樹同)
(4)若一個節點為葉子節點,那么編號比其大的節點均為葉子節點。
二、二叉樹的相關性質
2.1 二叉樹性質:
(1)在非空二叉樹的 ii 層上,至多有 2i−12i−1 個節點 (i≥1)(i≥1) 。
(2)在深度為 hh 的二叉樹上最多有 2h−12h−1 個節點 (k≥1)(k≥1) 。
(3)對於任何一棵非空的二叉樹,如果葉節點個數為 n0n0 ,度數為 22 的節點個數為 n2n2 ,則有: n0=n2+1n0=n2+1 。
2.2 完全二叉樹性質:
(1)具有 nn 個的結點的完全二叉樹的深度為 log2n+1log2n+1 。.
(2)如果有一顆有 nn 個節點的完全二叉樹的節點按層次序編號,對任一層的節點 i,(1≥i≥n)i,(1≥i≥n) 有:
(2.1)如果 i=1i=1 ,則節點是二叉樹的根,無雙親,如果 i>1i>1 ,則其雙親節點為 ⌊i/2⌋⌊i/2⌋ 。
(2.2)如果 2i>n2i>n 那么節點i沒有左孩子,否則其左孩子為 2i2i 。
(2.3)如果 2i+1>n2i+1>n 那么節點沒有右孩子,否則右孩子為 2i+12i+1 。
三、二叉樹的數據結構(排序方式)
想要遍歷一棵二叉樹,有兩種不同的策略:深度優先遍歷和寬度(廣度)優先遍歷。
其中深度優先遍歷策略有三種不同的方式:
前序遍歷:按根節點、左子樹、右子樹的順序遍歷。
中序遍歷:按左子樹、根節點、右子樹的順序遍歷。
后序遍歷:按左子樹、右子樹、根節點的順序遍歷。
四、python實現二叉樹
# 創建二叉樹節點 class Node(object): def __init__(self,item): self.item = item self.left = None self.right = None # 創建二叉樹 class Tree(object): # 構建一顆空二叉樹 def __init__(self): # 指針指向根節點,當前樹為空,指向None self.root = None # 添加子節點 def addNode(self,item): node = Node(item) cur = self.root # 判斷如果新節點是根節點 if self.root == None: self.root = node return # 如果樹不為空情況,需要通過隊列循環來遍歷節點是否為空 # 先將根節點指針放入列表,作為遍歷起始點 q = [cur] while q: # 刪除隊列中最左側元素 n = q.pop(0) # 判斷左節點是否為空 if n.left == None: n.left = node break else: q.append(n.left) # 判斷右節點是否為空 if n.right == None: n.right = node break else: q.append(n.right) # 樹的廣度遍歷 def travel(self): cur = self.root q = [cur] while q: # 刪除列表中最左側(最先進入的子節點)元素 n = q.pop(0) print(n.item) # 當前節點的左子節點不為None,說明子節點存在,追加子節點地址到列表 if n.left != None: q.append(n.left) # 當前節點的右子節點不為None,說明子節點存在,追加子節點地址到列表 if n.right != None: q.append(n.right) # 樹的深度遍歷(前序遍歷,中序遍歷,后序遍歷) # 前序遍歷(根左右) def frontTravel(self,root): # 判斷當子節點為空時,結束遞歸 if root == None: return # 獲取節點的值 print(root.item) # 通過遞歸獲取根左節點地址 self.frontTravel(root.left) # 通過遞歸獲取根右節點地址 self.frontTravel(root.right) # 中序遍歷(左根右) def midTravel(self,root): # 判斷當子節點為空時,結束遞歸 if root == None: return # 通過遞歸獲取根左節點地址 self.midTravel(root.left) # 獲取節點的值 print(root.item) # 通過遞歸獲取根右節點地址 self.midTravel(root.right) # 后序遍歷(左右根) def afterTravel(self,root): # 判斷當子節點為空時,結束遞歸 if root == None: return # 通過遞歸獲取根左節點地址 self.afterTravel(root.left) # 通過遞歸獲取根右節點地址 self.afterTravel(root.right) # 獲取節點的值 print(root.item)
測試:
# 測試 tree = Tree() tree.addNode(1) tree.addNode(2) tree.addNode(3) tree.addNode(4) tree.addNode(5) tree.addNode(6) # 廣度遍歷樹 # tree.travel() # 深度遍歷樹 # tree.frontTravel(tree.root) # 1 2 4 5 3 6 # tree.midTravel(tree.root) # 4 2 5 1 6 3 tree.afterTravel(tree.root) # 4 5 2 6 3 1
五、排序二叉樹
插入節點的准則:首先插入根節點。當插入其他節點的時候,需要和根節點做比較,比根節點小的節點插入樹的左側,大的插入樹的右側
class Node(): def __init__(self,item): self.item = item self.left = None self.right = None class SortTree(): def __init__(self): self.root = None def midTravel(self,root): if root == None: return #左根右 self.midTravel(root.left) print(root.item) self.midTravel(root.right) def insertNode(self,item): node = Node(item) cur = self.root #樹為空 if self.root == None: self.root = node return #樹為非空 while True: if cur.item > node.item: if cur.left == None: cur.left = node break else: cur = cur.left else: if cur.right == None: cur.right = node break else: cur = cur.right
測試:
t = SortTree() t.insertNode(3) t.insertNode(8) t.insertNode(3) t.insertNode(1) t.insertNode(1) t.midTravel(t.root) #結果:>>> 1 1 3 3 8