Chinese Usage Help Document in Python Treelib Multi-tree Data Structure
Tree is an important data structure for computer programming language. It has a wide range of applications, such as hierarchical data structure of file system and some algorithms in machine learning. treelib is created here to provide efficient implementation of tree data structure in Python.
1. Installation
Installation mainly through pip and easy_install
Under windows:
pip install treelib
Under Linux:
sudo easy_install -U treelib
License license:
Redistributed under Apache License (2.0) since version 1.3.0.
Source: Github:caesar0301/treelib
2. Class Definition
It is mainly divided into Tree and Node classes to support the implementation of multi-tree.
2.1.Tree class
Magic Method:
Constructor: Create a new tree or copy a tree by deep or shallow copy
Tree(self, tree=None, deep=False)
Length: Number of nodes returning to the tree, the same as Tree.size()
len(Tree)
str string: Tree object is converted to str object, which can be output
str(Tree)
Unicode string: Tree object is converted to unicode object, which can be output
unicode(Tree)
Method:
add_node(self, node, parent=None)
Add a node node to the tree, which is a Node class object and its parent node
all_nodes(self)
Return all nodes with list
children(self, nid)
Returns a child node with nid as identifier. If nid does not exist, it returns a list as empty.
contains(self, nid)
Check whether the tree contains nid-marked nodes
create_node(self, tag=None, identifier=None, parent=None, data=None)
Create a node on the tree with parent as parent (similar to creating a Node object, adding Node to add_node)
depth(self, node=None)
Returns the depth of the tree (int), and if a node is given, the depth of the tree rooted on that node is returned.
expand_tree(self, nid=None, mode=1, filter=None, key=None, reverse=False)
Python generator, loosely based on an algorithm of John R. Anderson, Albert T. Corbett, and Brian J. Reiser ('Essential LISP', page 239-241)
UPDATE: the @filter function is performed on Node object during traversing.
UPDATE: the @key and @reverse are present to sort nodes at each level.
get_node(self, nid)
Returns a node identified as nid, and returns NULL if NID does not exist
is_branch(self, nid)
Returns a list list of child node identifiers with nid as the node, and empty list if nid does not exist
leaves(self, root=None)
Returns a list of all leaf node objects, and if given root, a list of all leaf node objects in the tree with root as the root node
level(self, nid, filter=None)
Returns all nodes at the specified depth, and the root node is calculated at depth 0.
Update: @filter params is added to calculate level passing exclusive nodes.
link_past_node(self, nid)
The method of linking parent node and child node of a node and deleting the node from the tree
For example, if a a - > b - > C tree is deleted, then a - > C tree is left.
move_node(self, source, destination)
Move the source node to the destination child node
parent(self, nid)
Returns the parent node of the node identified by nid
paste(self, nid, new_tree, deepcopy=False)
Paste the tree, by connecting the root node of new_tree with the node identified by nid, setting deepcopy can make deep copy
Update: add @deepcopy of pasted tree.
paths_to_leaves(self)
Gets the identification path from the root node to each leaf node, returns a list list list (double list) that identifies the list list list, and the root node is not omitted.
For example, a tree:
Harry |___ Bill |___ Jane | |___ Diane | |___ George | |___ Jill | |___ Mary | |___ Mark
Output results:
[['harry', 'jane', 'diane', 'mary'], ['harry', 'jane', 'mark'], ['harry', 'jane', 'diane', 'george', 'jill'], ['harry', 'bill']]
remove_node(self, identifier)
Remove the node identified by nid and remove all its child nodes at the same time
Number of nodes whose return value is removed
remove_subtree(self, nid)
Remove a subtree with nid as the root node
The return value is to remove the tree of the subtree and return an empty tree if nid does not exist
This method is similar to remove_node(self,nid) with the same implementation effect but different return values:
remove_node returns the number of removed nodes
remove_subtree returns the tree that removed the subtree
It is recommended to use remove_node to delete nodes because remove_subtree consumes memory to store new trees (return values)
rsearch(self, nid, filter=None)
Traverse the path (branch) from the nid-marked node to the root node
save2file(self, filename, nid=None, level=0, idhidden=True, filter=None, key=None, reverse=False, line_type=u'ascii-ex', data_property=None)
Save the tree to a file for offline analysis
show(self, nid=None, level=0, idhidden=True, filter=None, key=None, reverse=False, line_type=u'ascii-ex', data_property=None)
Output tree structure
siblings(self, nid)
Returns the sibling node of the node identified by nid
The return value is a list of sibling nodes, the root node has no sibling nodes, and the empty list is returned.
size(self, level=None)
Returns the number of specified depth (level) nodes and, if not, the number of whole tree nodes.
subtree(self, nid)
Shallow copy method establishes a sub-tree with nid as the root node, and returns an empty tree if nid does not exist.
If you use a deep copy, use the constructor to create a new tree, as follows:
e.g. new_tree = Tree(t.subtree(t.root), deep=True)
to_dict(self, nid=None, key=None, sort=True, reverse=False, with_data=False)
Converting Trees to dict Dictionaries
to_json(self, with_data=False, sort=True, reverse=False)
Converting trees to JSON format output
2.2.Node class
Magic Method:
Constructor: Create a Node Node Object
variable | Name | Explain |
---|---|---|
tag | Label | Tree output is displayed, default is random value |
identifier | Identification | The tree is unique, non-repeatable, and defaults to random values. |
data | data | Storage node data |
Node(self, tag=None, identifier=None, expanded=True, data=None)
Method:
is_leaf(self)
Check if the node is a leaf node and return Boolean value
is_root(self)
Check if the node is the root node and return Boolean value
update_bpointer(self, nid)
Setting the _bpointer pointer
update_fpointer(self, nid, mode=0)
Setting _fpointer pointer
3. Practical application
From official help documents: treelib.readthedocs.io
3.1. Basic usage
The following example shows the basic method of building a tree
>>> from treelib import Node, Tree
>>> tree = Tree()
>>> tree.create_node("Harry", "harry") # root node
>>> 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")
>>> tree.show()
Harry
├── Bill
└── Jane
├── Diane
│ └── Mary
└── Mark
3.2.API sample
Following are some examples of API usage based on the above numbers
* Example 1: Extending a tree by special methods
>>> print(','.join([tree[node].tag for node in \
tree.expand_tree(mode=Tree.DEPTH)]))
Harry,Bill,Jane,Diane,Mary,Mark
- Example 2: Extending a tree with custom filtering
>>> print(','.join([tree[node].tag for node in \
tree.expand_tree(filter = lambda x: \
x.identifier != 'diane')]))
Harry,Bill,Jane,Mark
- Example 3: Get a subtree with''diane'as the root node
>>> sub_t = tree.subtree('diane')
>>> sub_t.show()
Diane
└── Mary
- Example 4: Replicate the subtree with''diane'as the root node
>>> new_tree = Tree()
>>> new_tree.create_node("n1", 1) # root node
>>> new_tree.create_node("n2", 2, parent=1)
>>> new_tree.create_node("n3", 3, parent=1)
>>> tree.paste('bill', new_tree)
>>> tree.show()
Harry
├── Bill
│ └── n1
│ ├── n2
│ └── n3
└── Jane
├── Diane
│ └── Mary
└── Mark
- Example 5: Delete existing nodes from the tree
>>> tree.remove_node(1)
>>> tree.show()
Harry
├── Bill
└── Jane
├── Diane
│ └── Mary
└── Mark
- Example 6: Move a node to another parent node
>>> tree.move_node('mary', 'harry')
>>> tree.show()
Harry
├── Bill
├── Jane
│ ├── Diane
│ └── Mark
└── Mary
- Example 7: Getting tree depth
>>> tree.depth()
2
- Example 8: Obtain the depth of the node
>>> node = tree.get_node("bill")
>>> tree.depth(node)
1
- Example 9: Output tree structure
Output in the form of "ascii-em":
>>> tree.show(line_type="ascii-em")
Harry
╠══ Bill
╠══ Jane
║ ╠══ Diane
║ ╚══ Mark
╚══ Mary
Output in JSON format:
>>> print(tree.to_json(with_data=True))
{"Harry": {"data": null, "children": [{"Bill": {"data": null}}, {"Jane": {"data": null, "children": [{"Diane": {"data": null}}, {"Mark": {"data": null}}]}}, {"Mary": {"data": null}}]}}
3.3. More Usage
Sometimes you need a tree to store your data structure. In the latest version of treelib, the. data attribute is supported and any data can be stored.
For example, define a Flower class:
>>> class Flower(object): \
def __init__(self, color): \
self.color = color
Flower trees can then be established:
>>> ftree = Tree()
>>> ftree.create_node("Root", "root", data=Flower("black"))
>>> ftree.create_node("F1", "f1", parent='root', data=Flower("white"))
>>> ftree.create_node("F2", "f2", parent='root', data=Flower("red"))
Output tree structure according to attributes of. data:
>>> ftree.show(data_property="color")
black
├── white
└── red
Note: Before version 1.2.5, you need to inherit and override Node class methods, such as:
>>> class FlowerNode(treelib.Node): \
def __init__(self, color): \
self.color = color
>>> # create a new node
>>> fnode = FlowerNode("white")