版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
因为需要查表,但是关键字有各种组合非常烦,为了不写一堆的if else决定弄个搜索树,叶子节点就是我要的结果,路径就是表中的关键字组合。之前都是用指针实现的各种链表 图 树,换成python后忽然不知道怎么办了。在网上搜了下,用python的list来实现,不过网上几乎都是二叉树的实现,木法只好自己写啦。这是按我的需求写的,如果要直接还得按实际情况略作修改。
树的显示使用graphviz这个包,不过仅仅pip是不行的,还需要去下个压缩包(请自行百度)
========================== 我是定妆照的分界线==================
好像还挺好看,哈哈~
======================= 我是答应我以后直接给出能直接运行的源码好吗的分界线====================
# -*- coding:utf-8 -*-
# name: 树型结构
# author: bqh
# datetime:2019/9/17 9:48
# =========================
from graphviz import Digraph
import os
import string
import random
os.environ["PATH"] += os.pathsep + r'D:\Program Files (x86)\graphviz2.38\release\bin'
class Node:
def __init__(self, parent=None, children=None, data=None, tag=None):
"""
结点数据结构
:param parent: 父节点
:param children: 子节点,列表结构
:param data: 数据域, 类型string
"""
if children is None:
children = []
self.tag = tag if tag is not None else ''.join(random.sample(string.ascii_letters + string.digits, 8))
self.parent = parent
self.data = data
self.children = children
class Tree:
def __init__(self, rootdata):
self.root = Node(data=rootdata)
def insert(self, parent_node, children_node):
children_node.parent = parent_node
parent_node.children.append(children_node)
def search(self, node, data):
"""
以node为根节点查找值为data的结点,返回
:param node: 根节点
:param data: 值域
:return:
"""
if node.data == data:
return node
elif len(node.children) == 0:
return None
else:
for child in node.children:
res = self.search(child, data)
if res is not None:
return res
return None
def get_leavesByDataRoute(self, data_list):
"""
根据数据域提供的列表查找该路径下的所有叶子集合
:param data_list: 路径的数据域列表,[子节点数据, ……]
:return: 该路径下的叶子数据集合
"""
leaves = set()
node = self.root
for data in data_list:
node = self.search(node, data)
for child in node.children:
if len(child.children) > 0:
leaves.add(child.data)
return leaves
def show(self, save_path=None):
"""
显示该树形结构
:return:
"""
from random import sample
colors = ['skyblue', 'tomato', 'orange', 'purple', 'green', 'yellow', 'pink', 'red']
plt = Digraph(comment='Tree')
def print_node(node):
color = sample(colors, 1)[0]
if len(node.children) > 0:
for child in node.children:
plt.node(child.tag, child.data, style='filled', color=color, fontname="Heiti")
plt.edge(node.tag, child.tag)
print_node(child)
plt.node(self.root.tag, self.root.data, style='filled', color=sample(colors, 1)[0])
print_node(self.root)
plt.view()
if save_path is not None:
plt.render(save_path)
def create(csvfile_name):
tree = Tree('tongue_color')
with open(csvfile_name, 'r', encoding='utf-8') as rf:
lines = rf.readlines()
for line in lines:
elements = line.split(',')
p = tree.root
# 前2列或4列是属性组合,作为搜索路径
for i in range(len(elements) - 5):
if len(elements[i]) == 0:
continue
q = tree.search(p, elements[i])
if q is None:
q = Node(data=elements[i])
tree.insert(p, q)
p = q
# 最后5列是证型,全部作为当前节点的叶子节点
for i in range(len(elements) - 5, len(elements)):
if len(elements[i].strip()) == 0:
continue
new_node = Node(data=elements[i])
tree.insert(p, new_node)
return tree
def tree_test():
tree = Tree('10')
root = tree.root
for i in range(7, 10):
node = Node(data=str(i))
tree.insert(root, node)
p = tree.search(root, '7')
child = Node(data=u'淡红')
tree.insert(p, child)
p = tree.search(root, '8')
for i in range(4, 6):
node = Node(data=str(i))
tree.insert(p, node)
tree.show()
if __name__ == '__main__':
file = r'E:\code\Tongue\TongueProposal\material\tongue_color.csv'
tree = create(file)
tree.show()
tongue_color.csv文件,就几行:
舌淡红,舌形瘦,血虚,,,,
舌淡红,舌形胖,湿,痰,阳虚,气虚,寒
舌红,,阴虚,暑,阳亢,津亏,
舌红,舌形瘦,阴虚,,,,
舌红,舌形胖,热,痰,湿,血热,
舌绛,,血热,热,阴虚,亡阴,
舌白,,血虚,阳虚,气虚,气陷,
舌白,舌形胖,阳虚,寒,湿,气虚,
舌紫,,阳虚,血瘀,痰,,