Python 树结构库treelib使用教程

树结构是一种常见且重要的数据结构。Python中的treelib库是对树结构的有效实现。在 treelib 库中,实现了两个类 TreeNode,分别用于创建多叉树和创建节点。

一、安装

pip install treelib

二、基本用法

2.1 创建多叉树

from treelib import Tree, Node

# 创建一棵多叉树
tree = Tree()  

Tree 类用于实例化一棵多叉树。有四个初始化参数:Tree(tree=None, deep=False, node_class=None, identifier=None),都有默认值。函数定义如下:

def __init__(self, tree=None, deep=False, node_class=None, identifier=None):
  • tree表示拷贝一棵已有的树,传入一个Tree的对象。
  • deep表示拷贝另一棵树时是否深拷贝。
  • node_class表示节点类,一般不需要使用,可以不管。
  • identifier表示树的id,在初始化时会默认分配一个唯一的id值,也可以手动指定一个id,保证是唯一的就行,树一旦创建完成,id就不能再修改。

2.2 添加节点

创建完多叉树后,我们可以基于tree.create_node()函数来添加节点。

# 添加节点
tree.create_node('Harry', 'harry')  # 根节点
tree.create_node('Jane', 'jane', parent='harry')
tree.create_node('Bill', 'bill', parent='harry')
tree.create_node('Diane', 'diane', parent='jane')
tree.create_node('Mary', 'mary', parent='diane')
tree.create_node('Mark', 'mark', parent='jane')

create_node(tag=None, identifier=None, parent=None, data=None): 创建一个节点并直接添加到树中。函数定义如下:

def create_node(self, tag=None, identifier=None, parent=None, data=None):
    """
    Create a child node for given @parent node. If ``identifier`` is absent,
    a UUID will be generated automatically.
    """
  • tag表示节点的标签,在控制台打印树的结构时显示的就是节点的标签,可以指定值,如果不指定值则默认等于id。
  • identifier表示节点的id,默认会分配一个唯一的id,也可以指定一个唯一id。这里要注意,id是唯一的,不能重复,标签是可以重复的但最好别重复。
  • parent表示节点的父节点,根节点可以不指定,不过,一棵树只能有一个根节点,如果树中已经有根节点了,parent还为空会报错。
  • data表示节点中保存的数据,可以是各种数据类型。

add_node(node, parent=None): 添加一个节点到树中。这个方法需要先用 Node 类创建好节点,第一个参数传入节点,第二参数同create_node()方法。

def add_node(self, node, parent=None):
    """
    Add a new node object to the tree and make the parent as the root by default.

    The 'node' parameter refers to an instance of Class::Node.
    """

2.2 输出树结构

tree.show()

这你,如果 tree.show()显示很多符号,而不是教程中所给的树结构时,可以使用
tree.show(line_type='ascii')

print(tree)

输出如下:

Harry
├── Bill
└── Jane
    ├── Diane
    │   └── Mary
    └── Mark

2.3 返回多叉树中的节点

2.3.1 tree.all_nodes()

all_nodes(): 返回多叉树中的所有节点,返回结果是一个节点对象构成的列表,节点的顺序是添加到树中的顺序。

print(tree.all_nodes())  # 返回多叉树中的节点

输出:

[Node(tag=Harry, identifier=harry, data=None), Node(tag=Jane, identifier=jane, data=None), Node(tag=Bill, identifier=bill, data=None), Node(tag=Diane, identifier=diane, data=None), Node(tag=Mary, identifier=mary, data=None), Node(tag=Mark, identifier=mark, data=None)]

直接打印节点,会将节点作为一个类对象打印出来。节点的tag、identifier和data三条属性可以单独调用,可以看到在不指定值时,tag与identifier相等,是一个系统分配的唯一值。

2.3.2 tree.all_nodes_itr()

all_nodes_itr(): 返回多叉树中的所有节点,返回结果是一个迭代器,节点的顺序是添加到树中的顺序。

for node in tree.all_nodes_itr():
    print(node)

输出:

Node(tag=Harry, identifier=harry, data=None)
Node(tag=Jane, identifier=jane, data=None)
Node(tag=Bill, identifier=bill, data=None)
Node(tag=Diane, identifier=diane, data=None)
Node(tag=Mary, identifier=mary, data=None)
Node(tag=Mark, identifier=mark, data=None)

2.3.3 tree.expand_tree()

expand_tree(): 返回多叉树中的所有节点id,返回结果是一个生成器,顺序是按深度优先遍历的顺序。可以传入过滤条件等参数来改变返回的生成器。

for id in tree.expand_tree():
    print(id)

输出:

harry
bill
jane
diane
mary
mark

2.4 判断是否为根/叶子节点

  • is_leaf(tree_id=None): 返回节点在树中的位置是不是叶节点。
  • is_root(tree_id=None): 返回节点在树中的位置是不是根节点。
for node in tree.all_nodes_itr():
    print(node)
    print('leaf:', node.is_leaf())
    print('root:', node.is_root())

输出:

Node(tag=Harry, identifier=harry, data=None)
leaf: False
root: True
Node(tag=Jane, identifier=jane, data=None)
leaf: False
root: False
Node(tag=Bill, identifier=bill, data=None)
leaf: True
root: False
Node(tag=Diane, identifier=diane, data=None)
leaf: False
root: False
Node(tag=Mary, identifier=mary, data=None)
leaf: True
root: False
Node(tag=Mark, identifier=mark, data=None)
leaf: True
root: False

2.5 多叉树的深度和叶子节点

2.5.1 多叉树的深度

print('tree depth:', tree.depth())

输出:

tree depth: 3

2.5.2 树的叶子节点

print('tree leaves:', tree.leaves())

输出:

tree leaves: [Node(tag=Bill, identifier=bill, data=None), Node(tag=Mary, identifier=mary, data=None), Node(tag=Mark, identifier=mark, data=None)]

2.5.3 到叶子节点的路径

print(tree.paths_to_leaves())

输出:

[['harry', 'bill'], ['harry', 'jane', 'diane', 'mary'], ['harry', 'jane', 'mark']]

2.6 其他用法

  • children(nid): 传入节点id,返回节点的所有子节点,返回结果是一个节点列表,如果没有子节点则返回空列表。

  • is_branch(nid): 传入节点id,返回节点的所有子节点id,返回结果是一个列表,如果没有子节点则返回空列表。

  • siblings(nid): 传入节点id,返回节点的所有兄弟节点,返回结果是一个节点列表,如果没有兄弟节点则返回空列表。

  • parent(nid): 传入节点id,返回节点的父节点,如果传入的是根节点,则返回None。

  • ancestor(nid, level=None): 传入节点id,返回节点的一个祖先节点,如果指定level则返回level层的祖先节点,如果不指定level则返回父节点,如果指定level比节点的层数大,则报错。

  • is_ancestor(ancestor, grandchild): 传入两个节点id,判断ancestor是不是grandchild的祖先,返回布尔值。

  • rsearch(nid, filter=None): 传入节点id,遍历节点到根节点的路径上的所有节点id,包含该节点和根节点,返回结果是一个生成器。可以传入过滤条件对结果进行过滤。

三、高级用法

  • 判断节点是否在多叉树中
  • 多叉树的合并和子树拷贝
  • 多叉树删除子树
  • 。。。

参考文献

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值