【資料結構與演算法】002—樹與二叉樹(Python)
阿新 • • 發佈:2018-12-26
概念
樹
樹是一類重要的非線性資料結構,是以分支關係定義的層次結構
定義:
樹(tree)是n(n>0)個結點的有限集T,其中: 有且僅有一個特定的結點,稱為樹的根(root)
當n>1時,其餘結點可分為m(m>0)個互不相交的有限集T1,T2,……Tm,其中每一個集合本身又是一棵樹,稱為根的子樹(subtree)
特點: 樹中至少有一個結點——根 樹中各子樹是互不相交的集合
基本術語
結點(node)——表示樹中的元素,包括資料項及若干指向其子樹的分支
結點的度(degree)——結點擁有的子樹數 葉子(leaf)——度為0的結點
孩子(child)——結點子樹的根稱為該結點的孩子
雙親(parents)——孩子結點的上層結點叫該結點的~
兄弟(sibling)——同一雙親的孩子
樹的度——一棵樹中最大的結點度數
結點的層次(level)——從根結點算起,根為第一層,它的孩子為第二層……
深度(depth)——樹中結點的最大層次數
森林(forest)——m(m0)棵互不相交的樹的集合
二叉樹
二叉樹是有限個元素的集合,該集合或者為空、或者有一個稱為根節點(root)的元素及兩個互不相交的、分別被稱為左子樹和右子樹的二叉樹組成。
- 二叉樹的每個結點至多隻有二棵子樹(不存在度大於2的結點),二叉樹的子樹有左右之分,次序不能顛倒。
- 二叉樹的第i層至多有2^{i-1}個結點
- 深度為k的二叉樹至多有2^k-1個結點;
- 對任何一棵二叉樹T,如果其終端結點數為N0,度為2的結點數為N2,則N0=N2+1
遍歷二叉樹
- 前序遍歷
若樹為空,則空操作返回。否則,先訪問根節點,然後前序遍歷左子樹,再前序遍歷右子樹。(W)型 (中 左 右) - 中序遍歷
若樹為空,則空操作返回。否則,從根節點開始(注意並不是先訪問根節點),中序遍歷根節點的左子樹,然後是訪問根節點,最後中序遍歷根節點的右子樹。(M)型,(左 中 右) - 後續遍歷
若樹為空,則空操作返回。否則,從左到右先葉子後節點的方式遍歷訪問左右子樹,最後訪問根節點。(左右中)逆時針型 (左 右 中) - 層序遍歷
若樹為空,則空操作返回。否則,從樹的第一層,也就是根節點開始訪問,從上到下逐層遍歷,在同一層中,按從左到右的順序結點逐個訪問。
實現方法
class Node:
def __init__(self,item):
self.item = item
self.child1 = None
self.child2 = None
class Tree:
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 []
result = [root.item]
left_item = self.preorder(root.child1)
right_item = self.preorder(root.child2)
return result + left_item + right_item
def inorder(self,root): # 中序序遍歷
if root is None:
return []
result = [root.item]
left_item = self.inorder(root.child1)
right_item = self.inorder(root.child2)
return left_item + result + right_item
def postorder(self,root): # 後序遍歷
if root is None:
return []
result = [root.item]
left_item = self.postorder(root.child1)
right_item = self.postorder(root.child2)
return left_item + right_item + result
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))
層序遍歷: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
先序遍歷: [0, 1, 3, 7, 8, 4, 9, 2, 5, 6]
中序遍歷: [7, 3, 8, 1, 9, 4, 0, 5, 2, 6]
後序遍歷: [7, 8, 3, 9, 4, 1, 5, 6, 2, 0]