樹形結構
基礎概念
1. 定義
樹(Tree)是n(n≥0)個節點的有限集合T,它滿足兩個條件:有且僅有一個特定的稱爲根(Root)的節點;其餘的節點可以分爲m(m≥0)個互不相交的有限集合T1、T2、……、Tm,其中每一個集合又是一棵樹,並稱爲其根的子樹(Subtree)。
2. 基本概念
一個節點的子樹的個數稱爲該節點的度數,一棵樹的度數是指該樹中節點的最大度數。
度數爲零的節點稱爲樹葉或終端節點,度數不爲零的節點稱爲分支節點。
一個節點的子樹之根節點稱爲該節點的子節點,該節點稱爲它們的父節點,同一節點的各個
子節點之間稱爲兄弟節點。一棵樹的根節點沒有父節點,葉節點沒有子節點。
節點的層數等於父節點的層數加一,根節點的層數定義爲一。樹中節點層數的最大值稱爲該樹的高度或深度。
二叉樹
1. 定義
二叉樹(Binary Tree)是n(n≥0)個節點的有限集合,它或者是空集(n=0),或者是由一個根節點以及兩棵互不相交的、分別稱爲左子樹和右子樹的二叉樹組成。二叉樹與普通有序樹不同,二叉樹嚴格區分左孩子和右孩子,即使只有一個子節點也要區分左右。
二叉樹第i(i≥1)層上的節點最多爲個。
深度爲k(k≥1)的二叉樹最多有 個節點。
在任意一棵二叉樹中,樹葉的數目比度數爲2的節點的數目多一。
滿二叉樹 :深度爲k(k≥1)時有 個節點的二叉樹。
二叉樹的遍歷
遍歷 :沿某條搜索路徑周遊二叉樹,對樹中的每一個節點訪問一次且僅訪問一次。
先序遍歷: 先訪問樹根,再訪問左子樹,最後訪問右子樹;
中序遍歷: 先訪問左子樹,再訪問樹根,最後訪問右子樹;
後序遍歷: 先訪問左子樹,再訪問右子樹,最後訪問樹根;
層次遍歷: 從根節點開始,逐層從左向右進行遍歷。
例如:
先序遍歷結果:A B D E G H C F
中序遍歷結果:D B G H E A C F
後序遍歷結果:D H G E B F C A
層次遍歷結果:A B C D E F G H
遞歸思想和實踐
1. 什麼是遞歸?
所謂遞歸函數是指一個函數的函數體中直接調用或間接調用了該函數自身的函數。這裏的直接調用是指一個函數的函數體中含有調用自身的語句,間接調用是指一個函數在函數體裏有調用了其它函數,而其它函數又反過來調用了該函數的情況。
2. 執行過程
遞推階段:從原問題出發,按遞歸公式遞推從未知到已知,最終達到遞歸終止條件。
迴歸階段:按遞歸終止條件求出結果,逆向逐步代入遞歸公式,迴歸到原問題求解。
3. 優點與缺點
優點:遞歸可以把問題簡單化,讓思路更爲清晰,代碼更簡潔
缺點:遞歸因系統環境影響大,當遞歸深度太大時,可能會得到不可預知的結果
示例:
"""
求一個數n的階乘
"""
# 遞歸函數
def recursion(n):
# 遞歸的終止條件
if n <= 1:
return 1
return n * recursion(n - 1)
print(recursion(3))
# 3 * 2 * 1 = 6
二叉樹的代碼實現
二叉樹順序存儲
二叉樹本身是一種遞歸結構,可以使用Python list 進行存儲。但是如果二叉樹的結構比較稀疏的話浪費的空間是比較多的。
空結點用None表示
非空二叉樹用包含三個元素的列表[d,l,r]表示,其中d表示根結點,l,r左子樹和右子樹。
"""
鏈式存儲二叉樹
"""
class TreeNode:
def __init__(self, data=None, left=None, right=None):
self.data = data
self.left = left
self.right = right
class BiTree:
def __init__(self, root=None):
self.root = root
def is_empty(self):
return self.root is None
# 先序遍歷
def pre_order(self, node):
if node is None:
return
print(node.data, end=" ")
self.pre_order(node.left)
self.pre_order(node.right)
# 中序遍歷
def mid_order(self, node):
if node is None:
return
self.mid_order(node.left)
print(node.data, end=" ")
self.mid_order(node.right)
# 後序遍歷
def post_order(self, node):
if node is None:
return
self.mid_order(node.left)
self.mid_order(node.right)
print(node.data, end=" ")
# 層次排序
@staticmethod
def tier_order(node):
queue = [node]
while queue:
temp = queue.pop(0)
print(temp.data, end=' ')
if temp.left:
queue.append(temp.left)
if temp.right:
queue.append(temp.right)
if __name__ == '__main__':
d = TreeNode('D')
e = TreeNode('E')
f = TreeNode('F')
g = TreeNode('G')
b = TreeNode('B', d, e)
c = TreeNode('C', f, g)
a = TreeNode('A', b, c)
tree = BiTree(a)
tree.pre_order(tree.root) # A B D E C F G
tree.mid_order(tree.root) # D B E A F C G
tree.post_order(tree.root) # D B E F C G A
tree.tier_order(tree.root) # A B C D E F G