Introduction à l'utilisation de la bibliothèque Python treelib pour créer un arbre multi-fourches
La bibliothèque treelib est une bibliothèque tierce pour Python. Cette bibliothèque implémente certaines méthodes courantes liées aux polytrees.
Un, installez treelib
pip install treelib
Dans la bibliothèque treelib, deux classes Tree et Node sont implémentées, qui sont utilisées pour créer des polytrees et créer des nœuds, respectivement.
Deuxièmement, créez un multi-arbre et ajoutez des nœuds
1. Créez un polytree
# coding=utf-8
from treelib import Tree, Node
tree = Tree()
tree.show()
print(tree.identifier)
résultat de l'opération:
Tree is empty
2f9fa5c8-e7aa-11ea-9b8b-b886873e4844
La classe Tree est utilisée pour instancier une arborescence multi-branches. Il existe quatre paramètres d'initialisation (tree = None, deep = False, node_class = None, identifier = None), qui ont tous des valeurs par défaut. tree signifie copier un arbre existant et passer dans un objet Tree. deep indique s'il faut copier en profondeur lors de la copie d'un autre arbre. node_class représente la classe de nœuds, n'a généralement pas besoin d'être utilisée, elle peut être ignorée. L'identifiant représente l'identifiant de l'arborescence. Une valeur d'identifiant unique est attribuée par défaut lors de l'initialisation. Vous pouvez également spécifier manuellement un identifiant pour vous assurer qu'il est unique. Une fois l'arborescence créée, l'identifiant ne peut pas être modifié.
2. Ajouter des nœuds au polytree
tree.create_node(tag='Node-5', identifier='node-5', data=5)
tree.create_node(tag='Node-10', identifier='node-10', parent='node-5', data=10)
tree.create_node('Node-15', 'node-15', 'node-10', 15)
tree.show()
node = Node(data=50)
tree.add_node(node, parent='node-5')
node_a = Node(tag='Node-A', identifier='node-A', data='A')
tree.add_node(node_a, parent='node-5')
tree.show()
résultat de l'opération:
Node-5
└── Node-10
└── Node-15
Node-5
├── Node-10
│ └── Node-15
├── Node-A
└── ddeb9b02-e7ab-11ea-b2ee-b886873e4844
create_node (tag = None, identifier = None, parent = None, data = None): Créez un nœud et ajoutez-le directement à l'arborescence. balise représente le libellé du nœud. Le libellé du nœud est affiché lorsque la structure de l'arborescence est imprimée sur la console. La valeur peut être spécifiée. Si la valeur n'est pas spécifiée, elle sera égale à id par défaut. L'identifiant représente l'identifiant du nœud, un identifiant unique est attribué par défaut ou un identifiant unique peut être spécifié. Il faut noter ici que l'identifiant est unique et ne peut pas être répété. Le libellé peut être répété mais il vaut mieux ne pas le répéter. parent représente le nœud parent du nœud. Le nœud racine peut ne pas être spécifié. Cependant, une arborescence ne peut avoir qu'un seul nœud racine. S'il y a déjà un nœud racine dans l'arborescence, une erreur sera signalée si le parent est vide. data représente les données stockées dans le nœud, qui peuvent être de différents types de données.
add_node (node, parent = None): ajoute un nœud à l'arborescence. Cette méthode doit utiliser la classe Node pour créer le nœud en premier, le premier paramètre est passé au nœud et le second paramètre est le même que la méthode create_node ().
Troisièmement, Node crée des nœuds et des méthodes dans la classe Node
1. Créer un nœud
La classe Node est utilisée pour créer des nœuds. Il existe quatre paramètres d'initialisation (tag = None, identifier = None, extended = True, data = None), tous avec des valeurs par défaut. La balise, l'identifiant et les données sont les mêmes que la méthode create_node () précédente. Développé signifie l'évolutivité du nœud, qui sera utilisé dans l'arborescence, vous pouvez le laisser seul, gardez simplement la valeur par défaut.
La classe Node pour créer un nœud est généralement utilisée en conjonction avec add_node () dans la classe Tree.
2. Les attributs et méthodes du nœud
print(node)
print('node id: ', node.identifier)
print('node tag:', node.tag)
print('node data:', node.data)
print('node is leaf: ', node.is_leaf())
print('node is root: ', node.is_root())
résultat de l'opération:
Node(tag=719f3842-e7af-11ea-8caa-b886873e4844, identifier=719f3842-e7af-11ea-8caa-b886873e4844, data=50)
node id: 719f3842-e7af-11ea-8caa-b886873e4844
node tag: 719f3842-e7af-11ea-8caa-b886873e4844
node data: 50
node is leaf: True
node is root: False
Si vous imprimez le nœud directement, le nœud sera imprimé en tant qu'objet de classe. Les trois attributs de la balise, de l'identifiant et des données du nœud peuvent être appelés séparément. On peut voir que lorsqu'aucune valeur n'est spécifiée, la balise est égale à l'identifiant, qui est une valeur unique attribuée par le système.
is_leaf (tree_id = None): renvoie si la position du nœud dans l'arborescence est un nœud feuille.
is_root (tree_id = None): renvoie si la position du nœud dans l'arborescence est le nœud racine.
Il existe d'autres méthodes dans la classe Node, qui sont principalement utilisées pour traiter le pointeur du nœud. En général, elles ne sont pas appelées directement, donc je ne les présenterai pas ici.
Quatrièmement, l'introduction de la méthode dans Tree
1. Renvoie le nombre de nœuds dans le polytree
tree.show()
print('tree len: ', len(tree))
print('tree size:', tree.size())
tree.create_node(tag='Node-20', identifier='node-20', parent='node-10', data=20)
tree.create_node(tag='Node-30', identifier='node-30', parent='node-15', data=30)
print('tree size:', tree.size())
résultat de l'opération:
Node-5
├── 6e75a77a-e92d-11ea-abfe-b886873e4844
├── Node-10
│ └── Node-15
└── Node-A
tree len: 5
tree size: 5
tree size: 7
show (): affiche la sortie de l'arborescence multi-fourches dans une structure arborescente. Vous pouvez transmettre des paramètres pertinents pour limiter la portée de l'affichage.
size (level = None): Renvoie le nombre de nœuds dans la multi-arborescence. Par défaut, tous les nœuds dans la multi-arborescence sont renvoyés, ce qui est identique à la méthode len (). Si le nombre de niveaux est spécifié, seul le nombre de nœuds de ce niveau sera renvoyé.
2. Renvoyez les nœuds dans le polytree
tree.show()
print(tree.all_nodes())
for node in tree.all_nodes_itr():
print(node)
for id in tree.expand_tree():
print(id)
résultat de l'opération:
Node-5
├── Node-10
│ ├── Node-15
│ │ └── Node-30
│ └── Node-20
├── Node-A
└── fcb7619a-e931-11ea-8946-b886873e4844
[Node(tag=Node-5, identifier=node-5, data=5), Node(tag=Node-10, identifier=node-10, data=10), Node(tag=Node-15, identifier=node-15, data=15), Node(tag=fcb7619a-e931-11ea-8946-b886873e4844, identifier=fcb7619a-e931-11ea-8946-b886873e4844, data=50), Node(tag=Node-A, identifier=node-A, data=A), Node(tag=Node-20, identifier=node-20, data=20), Node(tag=Node-30, identifier=node-30, data=30)]
Node(tag=Node-5, identifier=node-5, data=5)
Node(tag=Node-10, identifier=node-10, data=10)
Node(tag=Node-15, identifier=node-15, data=15)
Node(tag=fcb7619a-e931-11ea-8946-b886873e4844, identifier=fcb7619a-e931-11ea-8946-b886873e4844, data=50)
Node(tag=Node-A, identifier=node-A, data=A)
Node(tag=Node-20, identifier=node-20, data=20)
Node(tag=Node-30, identifier=node-30, data=30)
node-5
node-10
node-15
node-30
node-20
node-A
fcb7619a-e931-11ea-8946-b886873e4844
all_nodes (): renvoie tous les nœuds dans l'arborescence multi-fourches, le résultat renvoyé est une liste d'objets nœuds et l'ordre des nœuds est l'ordre dans lequel ils sont ajoutés à l'arborescence.
all_nodes_itr (): renvoie tous les nœuds dans le polytree, le résultat renvoyé est un itérateur et l'ordre des nœuds est l'ordre dans lequel ils sont ajoutés à l'arbre.
expand_tree (): Renvoie l'identifiant de tous les nœuds de l'arborescence multi-branches, le résultat renvoyé est un générateur et l'ordre est dans l'ordre de la traversée en profondeur d'abord. Vous pouvez transmettre des paramètres tels que les conditions de filtre pour modifier le générateur renvoyé.
3. Relation de nœud dans polytree
print('node-5 children:', tree.children('node-5'))
print('node-10 branch:', tree.is_branch('node-10'))
print('node-20 siblings:', tree.siblings('node-20'))
print('node-30 parent:', tree.parent('node-30'))
print('node-15 ancestor: ', tree.ancestor('node-15'))
print(tree.is_ancestor('node-15', 'node-30'))
for node in tree.rsearch('node-30'):
print(node)
résultat de l'opération:
node-5 children: [Node(tag=Node-10, identifier=node-10, data=10), Node(tag=2fbce8a8-e933-11ea-9304-b886873e4844, identifier=2fbce8a8-e933-11ea-9304-b886873e4844, data=50), Node(tag=Node-A, identifier=node-A, data=A)]
node-10 branch: ['node-15', 'node-20']
node-20 siblings: [Node(tag=Node-15, identifier=node-15, data=15)]
node-30 parent: Node(tag=Node-15, identifier=node-15, data=15)
node-15 ancestor: node-10
True
node-30
node-15
node-10
node-5
children (nid): Passez l'identifiant du nœud, retournez tous les nœuds enfants du nœud, le résultat renvoyé est une liste de nœuds, s'il n'y a pas de nœud enfant, retournez une liste vide.
is_branch (nid): passe l'ID du nœud, renvoie tous les ID de nœud enfant du nœud, le résultat de retour est une liste, s'il n'y a pas de nœud enfant, renvoie une liste vide.
siblings (nid): Passez l'identifiant du nœud, retournez tous les nœuds frères du nœud, le résultat de retour est une liste de nœuds, s'il n'y a pas de nœud frère, retournez une liste vide.
parent (nid): passe l'identifiant du nœud et renvoie le nœud parent du nœud. Si le nœud racine est transmis, il renvoie None.
ancestor (nid, level = None): passer l'identifiant du nœud, retourner un nœud ancêtre du nœud, si le niveau est spécifié, renvoyer le nœud ancêtre du niveau, si le niveau n'est pas spécifié, renvoyer le nœud parent, si le niveau spécifié est supérieur au nombre de niveaux du nœud, une erreur est signalée.
is_ancestor (ancestor, petit-enfant): transmettez deux identifiants de nœud, déterminez si l'ancêtre est un ancêtre du petit-enfant et retournez une valeur booléenne.
rsearch (nid, filter = None): Passez l'identifiant du nœud, parcourez tous les identifiants du nœud sur le chemin du nœud au nœud racine, y compris le nœud et le nœud racine, et le résultat renvoyé est un générateur. Vous pouvez passer des conditions de filtre pour filtrer les résultats.
4. La profondeur et les nœuds foliaires d'un polytree
print('tree depth:', tree.depth())
print('node-20 depth:', tree.depth(node='node-20'))
print('node-20 level:', tree.level('node-20'))
print('tree leaves:', tree.leaves())
print(tree.paths_to_leaves())
résultat de l'opération:
tree depth: 3
node-20 depth: 2
node-20 level: 2
tree leaves: [Node(tag=7e421cb4-e935-11ea-8e6d-b886873e4844, identifier=7e421cb4-e935-11ea-8e6d-b886873e4844, data=50), Node(tag=Node-A, identifier=node-A, data=A), Node(tag=Node-20, identifier=node-20, data=20), Node(tag=Node-30, identifier=node-30, data=30)]
[['node-5', '7e421cb4-e935-11ea-8e6d-b886873e4844'], ['node-5', 'node-A'], ['node-5', 'node-10', 'node-20'], ['node-5', 'node-10', 'node-15', 'node-30']]
depth (node = None): renvoie la hauteur du nœud, la hauteur du nœud racine est 0, augmentant séquentiellement. Si aucun nœud n'est spécifié, la hauteur de l'arbre est renvoyée.
level (nid, filter = None): renvoie la hauteur du nœud. Les résultats de level () et depth () sont les mêmes, mais la manière de passer les paramètres est différente.
feuilles (nid = None): renvoie tous les nœuds feuilles du multi-arbre, et le résultat est une liste de nœuds. Lorsque l'ID de nœud n'est pas spécifié, tous les nœuds feuilles de l'arborescence entière sont renvoyés par défaut. Lorsque l'ID de nœud est spécifié, tous les nœuds feuilles du sous-arbre avec le nœud spécifié comme nœud racine sont renvoyés.
path_to_leaves (): renvoie l'id de tous les nœuds sur le chemin allant du nœud racine à chaque nœud feuille. Le résultat de chaque nœud feuille est une liste et les résultats de tous les nœuds feuilles forment une liste. Le résultat final est donc une liste imbriquée de listes.
5. Déterminez si le nœud est dans le polytree et obtenez le nœud
print('node-10 is in tree:', tree.contains('node-10'))
print('node-100 is in tree:', tree.contains('node-100'))
print(tree.get_node('node-10'))
print(tree.get_node('node-100'))
tree.update_node('node-20', data=200)
print('data of node-20:', tree.get_node('node-20').data)
résultat de l'opération:
node-10 is in tree: True
node-100 is in tree: False
Node(tag=Node-10, identifier=node-10, data=10)
None
data of node-20: 200
contient (nid): passe l'ID du nœud, détermine si le nœud est dans l'arborescence et renvoie une valeur booléenne.
get_node (nid): passe l'identifiant du nœud, récupère le nœud de l'arborescence, renvoie l'objet nœud et renvoie None si l'ID du nœud transmis n'est pas dans l'arborescence.
update_node (nid, ** attrs): transmettez l'ID du nœud, modifiez la valeur d'attribut du nœud, quel paramètre à modifier est passé en tant que paramètre de mot-clé, et 0 ou plusieurs attributs peuvent être transmis.
6. Ajustez la relation des nœuds dans le polytree
tree.show()
tree.link_past_node('node-10')
tree.show()
tree.move_node('node-30', 'node-20')
tree.show()
résultat de l'opération:
Node-5
├── 488e66b6-e939-11ea-aa02-b886873e4844
├── Node-10
│ ├── Node-15
│ │ └── Node-30
│ └── Node-20
└── Node-A
Node-5
├── 488e66b6-e939-11ea-aa02-b886873e4844
├── Node-15
│ └── Node-30
├── Node-20
└── Node-A
Node-5
├── 488e66b6-e939-11ea-aa02-b886873e4844
├── Node-15
├── Node-20
│ └── Node-30
└── Node-A
link_past_node (nid): Passez l'identifiant du nœud, liez tous les nœuds enfants du nœud à son nœud parent, ce qui équivaut à supprimer le nœud de l'arborescence. Si l'ID de nœud n'est pas dans l'arborescence, une erreur est signalée.
move_node (source, destination): Passez deux identifiants de nœud, déplacez le nœud source dans un nœud enfant du nœud de destination. Si l'ID de nœud n'est pas dans l'arborescence, une erreur est signalée.
7. Fusion de plusieurs arbres et copie de sous-arbres
tree2 = Tree()
tree2.create_node(tag='Node-7', identifier='node-7', data=7)
tree2.create_node(tag='Node-17', identifier='node-17', parent='node-7', data=17)
tree2.show()
tree.paste('node-20', tree2)
tree.show()
tree3 = Tree()
tree3.create_node(tag='Node-8', identifier='node-8', data=8)
tree3.create_node(tag='Node-18', identifier='node-18', parent='node-8', data=18)
tree3.show()
tree.merge('node-A', tree3)
tree.show()
print(tree.subtree('node-20'))
résultat de l'opération:
Node-7
└── Node-17
Node-5
├── 4f603236-e93a-11ea-8577-b886873e4844
├── Node-15
├── Node-20
│ ├── Node-30
│ └── Node-7
│ └── Node-17
└── Node-A
Node-8
└── Node-18
Node-5
├── 4f603236-e93a-11ea-8577-b886873e4844
├── Node-15
├── Node-20
│ ├── Node-30
│ └── Node-7
│ └── Node-17
└── Node-A
└── Node-18
Node-20
├── Node-30
└── Node-7
└── Node-17
paste (nid, new_tree, deep = False): transmettez l'identifiant du nœud et un nouvel arbre, collez le nouvel arbre entier dans un sous-arbre du nœud spécifié, et le nœud racine du nouvel arbre devient un nœud enfant du nœud spécifié . Si le nœud n'est pas dans l'arborescence, une erreur est signalée.
merge (nid, new_tree, deep = False): transmettez l'identifiant du nœud et un nouvel arbre, fusionnez le nouvel arbre avec le nœud spécifié, après la fusion, le nœud racine du nouvel arbre n'est pas conservé, et les sous-arbres du nœud racine dans le nouvel arbre deviennent tous le sous-arbre spécifié du nœud. Si le nœud n'est pas dans l'arborescence, une erreur est signalée.
subtree (nid, identifier = None): transmettez l'ID du nœud et copiez le sous-arbre avec ce nœud en tant que nœud racine. Si le nœud n'est pas dans l'arborescence, une erreur est signalée.
8. Convertissez le polytree en dictionnaire et enregistrez-le dans un fichier
print(tree.to_dict())
print(tree.to_json())
tree.to_graphviz()
tree.save2file('demo_tree.tree')
résultat de l'opération:
{'Node-5': {'children': ['Node-15', {'Node-20': {'children': ['Node-30', {'Node-7': {'children': ['Node-17']}}]}}, {'Node-A': {'children': ['Node-18']}}, 'e1f2ba34-e93b-11ea-a5f9-b886873e4844']}}
{"Node-5": {"children": ["Node-15", {"Node-20": {"children": ["Node-30", {"Node-7": {"children": ["Node-17"]}}]}}, {"Node-A": {"children": ["Node-18"]}}, "e1f2ba34-e93b-11ea-a5f9-b886873e4844"]}}
digraph tree {
"node-5" [label="Node-5", shape=circle]
"node-15" [label="Node-15", shape=circle]
"node-20" [label="Node-20", shape=circle]
"node-A" [label="Node-A", shape=circle]
"e1f2ba34-e93b-11ea-a5f9-b886873e4844" [label="e1f2ba34-e93b-11ea-a5f9-b886873e4844", shape=circle]
"node-30" [label="Node-30", shape=circle]
"node-7" [label="Node-7", shape=circle]
"node-18" [label="Node-18", shape=circle]
"node-17" [label="Node-17", shape=circle]
"node-5" -> "e1f2ba34-e93b-11ea-a5f9-b886873e4844"
"node-5" -> "node-A"
"node-5" -> "node-15"
"node-5" -> "node-20"
"node-20" -> "node-30"
"node-20" -> "node-7"
"node-A" -> "node-18"
"node-7" -> "node-17"
}
to_dict (): Convertit l'arborescence en une structure de dictionnaire, les nœuds frères sont exprimés sous forme de relation parallèle par une liste et les nœuds parent et enfant sont exprimés sous forme de relation clé-valeur par un dictionnaire. Enfin, le résultat de la conversion est renvoyé.
to_json (): Convertit l'arbre en json, la structure des données est la même que to_dict (), mais le format est différent. Enfin, le résultat de la conversion est renvoyé.
to_graphviz (): Convertit l'arbre en la structure d'un graphe visuel, pas de valeur de retour.
save2file (filename): enregistre l'arborescence dans un fichier spécifié. Après l'exécution, il générera un fichier de nom de fichier sous le chemin actuel et écrira le diagramme de structure de l'arborescence dans le fichier. Lorsque le fichier du même nom existe, il être ajouté et écrit sans écrasement.
Ces quatre méthodes ont de nombreux paramètres de mot-clé, qui peuvent être spécifiés pour modifier le résultat de la conversion.
9. Sous-arborescence de suppression multitree
tree.show()
print('remover node: ', tree.remove_node('node-7'))
tree.show()
print(tree.remove_subtree('node-20'))
tree.show()
résultat de l'opération:
Node-5
├── 9e0bce40-e93d-11ea-99e7-b886873e4844
├── Node-15
├── Node-20
│ ├── Node-30
│ └── Node-7
│ └── Node-17
└── Node-A
└── Node-18
remover node: 2
Node-5
├── 9e0bce40-e93d-11ea-99e7-b886873e4844
├── Node-15
├── Node-20
│ └── Node-30
└── Node-A
└── Node-18
Node-20
└── Node-30
Node-5
├── 9e0bce40-e93d-11ea-99e7-b886873e4844
├── Node-15
└── Node-A
└── Node-18
remove_node (identificateur): transmettez l'ID du nœud, supprimez le nœud en tant que sous-arbre du nœud racine et renvoyez le nombre de nœuds supprimés.
remove_subtree (nid, identifier = None): transmettez l'ID du nœud, supprimez le nœud en tant que sous-arbre du nœud racine et renvoyez le sous-arbre supprimé.