Python3&資料結構之二叉樹
實現二叉樹以及遍歷
在電腦科學中,二叉樹是每個結點最多有兩個子樹的樹結構。通常子樹被稱作“左子樹”(left subtree)和“右子樹”(right subtree)。二叉樹常被用於實現二叉查詢樹和二叉堆。
二叉樹是遞迴定義的,其結點有左右子樹之分,邏輯上二叉樹有五種基本形態:
(1)空二叉樹——如圖(a);
(2)只有一個根結點的二叉樹——如圖(b);
(3)只有左子樹——如圖(c);
(4)只有右子樹——如圖(d);
(5)完全二叉樹——如圖(e)。
樹和二叉樹有兩個主要差別:
(1)樹中結點的最大度數沒有限制,而二叉樹結點的最大度數為2;
(2)樹的結點無左、右之分,而二叉樹的結點有左、右之分。
二叉樹的性質:
(1)二叉樹第i層上的結點數目最多為2^(i-1)(i>=1);
(2)深度為k的二叉樹至多有(2^k)-1個結點(k>=1);
(3)包含n個結點的二叉樹的高度至少為(logn)+1;(log預設為以2為底);
(4)在任意一棵二叉樹中,若終端結點的個數為n0,度為2的結點數為n2,則n0=n2+1。
二叉樹的種類:
(1)滿二叉樹:如果二叉樹中所有分支節點的度都為2,則稱它為一棵滿二叉樹。滿二叉樹是一般二叉樹的子集;
(2)完全二叉樹:對於一棵高度為h的二叉樹,如果其第0層至第h-1層的結點都滿(也就是說,對所有0≤i≤h-1,第i層有2^i個結點)。如果最下一層的結點不滿,則所有結點在最左邊連續排列,空位都在右邊。這樣的二叉樹就是一棵完全二叉樹;
(3)平衡二叉樹:平衡二叉樹(Self-balancing binary search tree)又被稱為AVL樹(有別於AVL演算法),且具有以下性質:它是一 棵空樹或它的左右兩個子樹的高度差的絕對值不超過1,並且左右兩個子樹都是一棵平衡二叉樹。平衡二叉樹的常用實現方法有紅黑樹、AVL、替罪羊樹、Treap、伸展樹等。 最小二叉平衡樹的節點的公式如下 F(n)=F(n-1)+F(n-2)+1 這個類似於一個遞迴的數列,可以參考Fibonacci(斐波那契)數列,1是根節點,F(n-1)是左子樹的節點數量,F(n-2)是右子樹的節點數量。
對於平衡二叉樹要特別注意的是,不要求非葉節點都有兩個子結點,僅要求兩個子樹的高度差的絕對值不超過1,或者為空樹。
關於遍歷:
設L、D、R分別表示遍歷左子樹、訪問根結點和遍歷右子樹, 則對一棵二叉樹的遍歷有三種情況:DLR(稱為先根次序遍歷),LDR(稱為中根次序遍歷),LRD (稱為後根次序遍歷)。
具體的程式碼部分:
class Node(object):
def __init__(self,item):
self.item = item
self.child1 = None
self.child2 = None
class Tree(object):
def __init__(self):
self.root = None
def add(self,item):
node = Node(item)
if self.root is None:
self.root = node
else:
q = [self.root]
while True:
pop_node = q.pop(0)
if pop_node.child1 is None:
pop_node.child1 = node
return
elif pop_node.child2 is None:
pop_node.child2 = node
return
else:
q.append(pop_node.child1)
q.append(pop_node.child2)
def traverse(self):#層次遍歷(寬度優先遍歷)
if self.root is None:
return None
q = [self.root]
res = [self.root.item]
while q != []:
pop_node = q.pop(0)
if pop_node.child1 is not None:
q.append(pop_node.child1)
res.append(pop_node.child1.item)
if pop_node.child2 is not None:
q.append(pop_node.child2)
res.append(pop_node.child2.item)
return res
def preorder(self,root):#先序遍歷
if root is None:
return []
res = [root.item]
left_item = self.preorder(root.child1)
right_item = self.preorder(root.child2)
return res + left_item + right_item
def inorder(self,root):#中序遍歷
if root is None:
return []
res = [root.item]
left_item = self.inorder(root.child1)
right_item = self.inorder(root.child2)
return left_item + res + right_item
def postorder(self,root):#後序遍歷
if root is None:
return []
res = [root.item]
left_item = self.postorder(root.child1)
right_item = self.postorder(root.child2)
return left_item + right_item + res
if __name__ == '__main__':
t = Tree()
for i in range(10):
t.add(i)
print("層序遍歷:",t.traverse())
print("先序遍歷:", t.preorder(t.root))
print("中序遍歷:", t.inorder(t.root))
print("後序遍歷:", t.postorder(t.root))
參考文獻:
[1] https://baike.baidu.com/item/%E4%BA%8C%E5%8F%89%E6%A0%91/1602879?fr=aladdin
[2] https://blog.csdn.net/mxz19901102/article/details/80071864