实现二叉树以及遍历
在计算机科学中,二叉树是每个结点最多有两个子树的树结构。通常子树被称作“左子树”(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