二叉树
⼆叉树的性质(特性)
- 性质1: 在⼆叉树的第i层上⾄多有2^(i-1)个结点(i>0
- 性质2: 深度为k的⼆叉树⾄多有2^k - 1个结点(k>0)
- 性质3: 对于任意⼀棵⼆叉树,如果其叶结点数为N0,⽽度数为2的结点总数 为N2,则N0=N2+1;
- 性质4:具有n个结点的完全⼆叉树的深度必为 log2(n+1)
- 性质5:对完全⼆叉树,若从上⾄下、从左⾄右编号,则编号为i 的结点,其左 孩⼦编号必为2i,其右孩⼦编号必为2i+1;其双亲的编号必为i/2(i=1 时为 根,除外)
⼆叉树的节点表示以及树的创建
- 通过使⽤Node类中定义三个属性,分别为elem本身的值,还有lchild左孩⼦ 和rchild右孩⼦
class Node(object):
"""节点类"""
def __init__(self, elem=-1, lchild=None, rchild=None):
self.elem = elem
self.lchild = lchild
self.rchild = rchild
- 树的创建,创建⼀个树的类,并给⼀个root根节点,⼀开始为空,随后添加节 点
class Tree(object):
"""树类"""
def __init__(self, root=None):
self.root = root
def add(self, elem):
"""为树添加节点"""
node = Node(elem)
#如果树是空的,则对根节点赋值
if self.root == None:
self.root = node
else:
queue = []
queue.append(self.root)
#对已有的节点进行层次遍历
while queue:
#弹出队列的第一个元素
cur = queue.pop(0)
if cur.lchild == None:
cur.lchild = node
return
elif cur.rchild == None:
cur.rchild = node
return
else:
#如果左右子树都不为空,加入队列继续判断
queue.append(cur.lchild)
queue.append(cur.rchild)
二叉树的遍历
- 深度优先一般用递归,广度优先一般用队列。一般情况下能用递归实现的算法大部分也能用堆栈来实现。
深度优先遍历
-
深度遍历有重要的三种方法。这三种方式常被用于访问树的节点,它们之间的不同在于访问每个节点的次序不同。这三种遍历分别叫做先序遍历(preorder),中序遍历(inorder)和后序遍历(postorder)。
- 先序遍历(根节点->左子树->右子树)
def preorder(self, root): """递归实现先序遍历""" if root == None: return print root.elem self.preorder(root.lchild) self.preorder(root.rchild)
- 中序遍历(左子树->根节点->右子树)
def inorder(self, root): """递归实现中序遍历""" if root == None: return self.inorder(root.lchild) print root.elem self.inorder(root.rchild)
- 后序遍历 (左子树->右子树->根节点)
def postorder(self, root): """递归实现后续遍历""" if root == None: return self.postorder(root.lchild) self.postorder(root.rchild) print root.elem
- 三种遍历案例
广度优先遍历(层次遍历)
- 从树的root开始,从上到下从从左到右遍历整个树的节点
-
def breadth_travel(self):
"""利用队列实现树的层次遍历"""
if root == None:
return
queue = []
queue.append(root)
while queue:
node = queue.pop(0)
print node.elem,
if node.lchild != None:
queue.append(node.lchild)
if node.rchild != None:
queue.append(node.rchild)
完整测试代码
class Node(object):
"""结点类"""
def __init__(self, item):
self.item = item
self.lchild = None
self.rchild = None
class BinaryTree(object):
"""二叉树"""
def __init__(self,node=None):
self.root = node
def add(self, item):
"""广度优先遍历"""
if self.root is None:
self.root = Node(item)
return
queue = []
queue.append(self.root)
while len(queue) > 0:
node = queue.pop(0)
if not node.lchild:
node.lchild = Node(item)
return
else:
queue.append(node.lchild)
if not node.rchild:
node.rchild = Node(item)
return
else:
queue.append(node.rchild)
def breadh_travel(self):
"""广度优先遍历"""
if self.root is None:
return
queue = []
queue.append(self.root)
while len(queue)>0:
node = queue.pop(0)
print(node.item, end=" ")
if node.lchild:
queue.append(node.lchild)
if node.rchild:
queue.append(node.rchild)
def preorder_travel(self, root):
"""先序遍历 根,左,右"""
if root:
print(root.item,end=" ")
self.preorder_travel(root.lchild)
self.preorder_travel(root.rchild)
def inorder_travel(self, root):
"""中序遍历 左,根,右"""
if root:
self.inorder_travel(root.lchild)
print(root.item, end=" ")
self.inorder_travel(root.rchild)
def postorder_travel(self, root):
"""后序遍历,左,右,根"""
if root:
self.postorder_travel(root.lchild)
self.postorder_travel(root.rchild)
print(root.item,end=" ")
if __name__ == '__main__':
tree = BinaryTree()
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)
tree.breadh_travel()
print(" ")
tree.preorder_travel(tree.root)
print(" ")
tree.inorder_travel(tree.root)
print(" ")
tree.postorder_travel(tree.root)
print(" ")