Chinese Usage Help Document in Python Treelib Multi-tree Data Structure

Posted by ari_aaron on Wed, 10 Jul 2019 00:22:51 +0200

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")

Topics: ascii Python pip JSON