python数据结构之二叉树的遍历
python数据结构之二叉树的遍历
二叉树
二叉树是每个结点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。二叉树常被用于实现二叉查找树和二叉堆。一棵深度为k,且有2^k-1个节点的二叉树,称为满二叉树。这种树的特点是每一层上的节点数都是最大节点数。而在一棵二叉树中,除最后一层外,若其余层都是满的,并且最后一层或者是满的,或者是在右边缺少连续若干节点,则此二叉树为完全二叉树。具有n个节点的完全二叉树的深度为floor(log2n)+1。深度为k的完全二叉树,至少有2k-1个叶子节点,至多有2k-1个节点。
定义
二叉树是一个连通的无环图,并且每一个顶点的度不大于3。有根二叉树还要满足根结点的度不大于2。有了根结点之后,每个顶点定义了唯一的父结点,和最多2个子结点。然而,没有足够的信息来区分左结点和右结点。如果不考虑连通性,允许图中有多个连通分量,这样的结构叫做森林。
相关术语
树的结点(node):包含一个数据元素及若干指向子树的分支;
孩子结点(child node):结点的子树的根称为该结点的孩子;
双亲结点:B 结点是A 结点的孩子,则A结点是B 结点的双亲;
兄弟结点:同一双亲的孩子结点; 堂兄结点:同一层上结点;
祖先结点: 从根到该结点的所经分支上的所有结点
子孙结点:以某结点为根的子树中任一结点都称为该结点的子孙
结点层:根结点的层定义为1;根的孩子为第二层结点,依此类推;
树的深度:树中最大的结点层
结点的度:结点子树的个数
树的度: 树中最大的结点度。
叶子结点:也叫终端结点,是度为 0 的结点;
分枝结点:度不为0的结点;
有序树:子树有序的树,如:家族树;
无序树:不考虑子树的顺序;
二叉树性质
(1) 在非空二叉树中,第i层的结点总数不超过 , i>=1;
(2) 深度为h的二叉树最多有 个结点(h>=1),最少有h个结点;
(3) 对于任意一棵二叉树,如果其叶结点数为N0,而度数为2的结点总数为N2,则N0=N2+1;
(4) 具有n个结点的完全二叉树的深度为 (注:[ ]表示向下取整)
(5)有N个结点的完全二叉树各结点如果用顺序方式存储,则结点之间有如下关系:
若I为结点编号则 如果I>1,则其父结点的编号为I/2;
如果2I<=N,则其左孩子(即左子树的根结点)的编号为2I;若2I>N,则无左孩子;
如果2I+1<=N,则其右孩子的结点编号为2I+1;若2I+1>N,则无右孩子。
(6)给定N个节点,能构成h(N)种不同的二叉树。
h(N)为卡特兰数的第N项。h(n)=C(2*n,n)/(n+1)。
(7)设有i个枝点,I为所有枝点的道路长度总和,J为叶的道路长度总和J=I+2i
class Node(object):
"""树节点"""
def __init__(self, item):
self.item = item
self.left_child = None
self.right_child = None
class BinaryTree(object):
"""二叉树"""
def __init__(self):
self.root = None
def is_empty(self):
"""判断二叉树是否为空"""
return self.root is None
def add(self, item):
"""添加树节点"""
node = Node(item)
if self.root is None:
self.root = node
return
temp = [self.root]
while temp:
current_node = temp.pop(0)
if current_node.left_child:
temp.append(current_node.left_child)
else:
current_node.left_child = node
return
if current_node.right_child:
temp.append(current_node.right_child)
else:
current_node.right_child = node
return
def breadth_traversal(self):
"""广度遍历"""
if self.root is None:
return
temp = [self.root]
while temp:
current_node = temp.pop(0)
print(current_node.item, end=' ')
if current_node.left_child:
temp.append(current_node.left_child)
if current_node.right_child:
temp.append(current_node.right_child)
print()
def preorder_traversal(self, node):
"""先序遍历"""
if node is None:
return
print(node.item, end=' ')
self.preorder_traversal(node.left_child)
self.preorder_traversal(node.right_child)
def inorder_traversal(self, node):
"""中序遍历"""
if node is None:
return
self.inorder_traversal(node.left_child)
print(node.item, end=' ')
self.inorder_traversal(node.right_child)
def postorder_traversal(self, node):
"""后序遍历"""
if node is None:
return
self.postorder_traversal(node.left_child)
self.postorder_traversal(node.right_child)
print(node.item, end=' ')
if __name__ == '__main__':
tree = BinaryTree()
print(tree.is_empty())
tree.add(0)
tree.add(1)
tree.add(2)
tree.add(3)
tree.add(4)
tree.add(5)
tree.add(6)
tree.add(7)
tree.add(8)
tree.add(9)
print(tree.is_empty())
tree.breadth_traversal()
tree.preorder_traversal(tree.root)
print()
tree.inorder_traversal(tree.root)
print()
tree.postorder_traversal(tree.root)