Python binarytree库的用法介绍
binarytree 库是一个 Python 的第三方库。这个库实现了一些二叉树相关的常用方法,使用二叉树时,可以直接调用,不需要再自己实现。
同时,binarytree 里还实现了二叉搜索树和堆,可以直接调用。
一、安装binarytree
pip install binarytree
在binarytree库中,可以供我们导入使用的有1个类和5个函数。下面会依次介绍每一个类或函数的用法。
__all__ = ['Node', 'tree', 'bst', 'heap', 'build', 'get_parent']
二、tree生成一棵普通二叉树
# coding=utf-8
from binarytree import *
tree0 = tree()
print('tree0:', tree0)
tree1 = tree(height=2, is_perfect=True)
print('tree1:', tree1)
tree2 = tree(height=2, is_perfect=False)
print('tree2:', tree2)
运行结果:
tree0:
_______13_____
/ \
___11__ _0__
/ \ / \
1 6 10 8
\ / \ / / \
14 2 3 5 9 4
tree1:
__2__
/ \
3 4
/ \ / \
1 5 6 0
tree2:
2__
/ \
0 6
/ /
3 1
tree(height=3, is_perfect=False): 用于生成一棵随机的二叉树,返回值是根节点。有两个参数,height 表示树的高度,默认为3,支持范围为0~9的整数,超出范围会报错,is_perfect 表示二叉树是否为满二叉树,默认为False,如果为True则一定是满二叉树,如果为False则不一定为满二叉树。生成的树是随机的,所以每次运行结果不一样。
满二叉树:所有叶节点都在最底层的完全二叉树称为满二叉树。满二叉树是完全二叉树中的特殊情况,除了满足完全二叉树的特征,还满足所有叶节点都在最底层。
三、bst生成一棵二叉搜索树
bst0 = bst()
print('bst0:', bst0)
bst1 = bst(height=2, is_perfect=True)
print('bst1:', bst1)
bst2 = bst(height=2, is_perfect=False)
print('bst2:', bst2)
运行结果:
bst0:
____4______
/ \
0__ __11___
\ / \
3 8 _13
/ / \ / \
1 7 9 12 14
bst1:
__3__
/ \
1 5
/ \ / \
0 2 4 6
bst2:
__3
/ \
1 4
/ \
0 2
bst(height=3, is_perfect=False): 用于生成一棵随机的二叉搜索树,返回值是根节点。有两个参数,height 表示树的高度,默认为3,支持范围为0~9的整数,超出范围会报错。is_perfect 表示二叉搜索树是否为满二叉树,默认为False,如果为True则一定是满二叉树,如果为False则不一定为满二叉树。如果 is_perfect 为False生成的树是随机的,所以每次运行结果不一样,如果 is_perfect 为True,则每次生成的二叉搜索树都一样。
二叉搜索树具有如下特性:
1. 如果二叉树的左子树不为空,则左子树上所有节点的值均小于它的根节点的值。
2. 如果二叉树的右子树不为空,则右子树上所有节点的值均大于它的根节点的值。
3. 如果独立地看,左子树、右子树也分别为二叉搜索树,用递归的思想,直到树的叶节点。
四、heap生成一个堆
heap0 = heap()
print('heap0:', heap0)
heap1 = heap(height=2, is_max=True, is_perfect=True)
print('heap1:', heap1)
heap2 = heap(height=2, is_max=False, is_perfect=True)
print('heap2:', heap2)
heap3 = heap(height=2, is_max=False, is_perfect=False)
print('heap3:', heap3)
运行结果:
heap0:
_______14________
/ \
__10__ ____13__
/ \ / \
8 9 12 5
/ \ / \ / \ / \
7 2 6 3 1 11 4 0
heap1:
__6__
/ \
5 4
/ \ / \
1 2 3 0
heap2:
__0__
/ \
4 1
/ \ / \
6 5 2 3
heap3:
__1
/ \
4 3
/ \
6 5
heap(height=3, is_max=True, is_perfect=False): 用于生成一个随机的堆,返回值是根节点。有三个参数,height 表示堆的高度,默认为3,支持范围为0~9的整数,超出范围会报错。is_max 表示是否为大顶堆,默认为True,如果为True则是大顶堆,如果为False则是小顶堆。is_perfect 表示堆是否为满二叉树,默认为False,如果为True则一定是满二叉树,如果为False则不一定为满二叉树。生成的树是随机的,所以每次运行结果不一样。
堆结构分为大顶堆和小顶堆:
大顶堆:每个节点(叶节点除外)的值都大于等于其子节点的值,根节点的值是所有节点中最大的。
小顶堆:每个节点(叶节点除外)的值都小于等于其子节点的值,根节点的值是所有节点中最小的。
五、build按广度优先生成一棵二叉树
values = [10, 17, 50, 7, 30, 24, 27, 45, 15, 5, 36, 21]
build_tree = build(values)
print(build_tree)
print(build_tree.values)
运行结果:
_________10______
/ \
___17__ _50
/ \ / \
_7 30 _24 27
/ \ / \ /
45 15 5 36 21
[10, 17, 50, 7, 30, 24, 27, 45, 15, 5, 36, 21]
build(values): 根据提供的数据列表生成一棵二叉树,返回值是根节点。将数据列表中的数据按广度优先的方式添加到二叉树中(层序遍历,即从上到下、从左到右)。
六、获取节点的父节点
values = [10, 17, 50, 7, 30, 24, 27, 45, 15, 5, 36, 21]
build_tree = build(values)
print(build_tree)
child_node = build_tree.left.right
print('child_node: ', child_node.value)
parent = get_parent(build_tree, child_node)
print('parent_node: ', parent.value)
运行结果:
_________10______
/ \
___17__ _50
/ \ / \
_7 30 _24 27
/ \ / \ /
45 15 5 36 21
child_node: 30
parent_node: 17
get_parent(root, child): 根据二叉树中的节点找到它的父节点,返回值是父节点。有两个参数,root 表示二叉树的根节点,child 表示子节点。如果 child 传入的值是根节点,则返回的父节点结果为 None 。
七、通过创建节点来构造二叉树
root = Node(10)
root.left = Node(5)
root.right = Node(15)
print(root)
运行结果:
10
/ \
5 15
Node(object)类: Node是一个类,用于创建一个节点。初始化时有三个参数,value 表示节点的值,没有默认值,是必传参数,且传入的参数必须是数字,不能是字符串等,否则抛出类型错误的异常。left 和 right 分别表示节点的左子节点和右子节点,默认为空,left 和 right 的值必须是 Node 类的实例,否则抛出类型错误的异常。
data = [10, 17, 50, 7, 30, 24, 27, 45, 15, 5, 36, 21]
nodes = [None if i is None else Node(i) for i in data]
root = nodes[0]
root.left = nodes[1]
root.right = nodes[2]
root.left.left = nodes[3]
root.left.right = nodes[4]
root.right.left = nodes[5]
root.right.right = nodes[6]
root.pprint()
print('层序遍历: ', root.levelorder)
print('先序遍历: ', root.preorder)
print('中序遍历: ', root.inorder)
print('后序遍历: ', root.postorder)
运行结果:
____10___
/ \
17 _50
/ \ / \
7 30 24 27
层序遍历: [Node(10), Node(17), Node(50), Node(7), Node(30), Node(24), Node(27)]
先序遍历: [Node(10), Node(17), Node(7), Node(30), Node(50), Node(24), Node(27)]
中序遍历: [Node(7), Node(17), Node(30), Node(10), Node(24), Node(50), Node(27)]
后序遍历: [Node(7), Node(30), Node(17), Node(24), Node(27), Node(50), Node(10)]
Node类用于创建节点,然后通过left和right两个属性来将节点关联到一棵树中,这相对于批量添加来说,操作有点繁琐。
Node类中实现了很多的方法,并且很多方法都使用 @property 装饰成了属性,可以直接用根节点来调用这些属性。如上面代码中的四种遍历方法。
想知道 Node 类中的所有方法,可以使用内置方法 dir() 将所有方法打印出来。如 properties 属性,可以返回当前二叉树的每一个属性值,返回一个字典。
print(dir(root))
print(root.properties)
运行结果:
['__class__', '__delattr__', '__delitem__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'height', 'inorder', 'is_balanced', 'is_bst', 'is_complete', 'is_max_heap', 'is_min_heap', 'is_perfect', 'is_strict', 'is_symmetric', 'leaf_count', 'leaves', 'left', 'levelorder', 'levels', 'max_leaf_depth', 'max_node_value', 'min_leaf_depth', 'min_node_value', 'postorder', 'pprint', 'preorder', 'properties', 'right', 'size', 'val', 'validate', 'value', 'values']
{'height': 2, 'size': 7, 'is_max_heap': False, 'is_min_heap': False, 'is_perfect': True, 'is_strict': True, 'is_complete': True, 'leaf_count': 4, 'min_node_value': 7, 'max_node_value': 50, 'min_leaf_depth': 2, 'max_leaf_depth': 2, 'is_bst': False, 'is_balanced': True, 'is_symmetric': False}
关于Node类中其他属性的用法就不一一介绍了,这些属性一般都是能见名知义的。
binarytree 库的源码并不复杂,可供调用的5个函数代码都很少,大部分代码是实现Node类,在Node类中,代码多是因为实现了很多常用的方法,单独看其中一个方法时,代码并不多。