因爲需要查表,但是關鍵字有各種組合非常煩,爲了不寫一堆的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文件,就幾行:
舌淡紅,舌形瘦,血虛,,,,
舌淡紅,舌形胖,溼,痰,陽虛,氣虛,寒
舌紅,,陰虛,暑,陽亢,津虧,
舌紅,舌形瘦,陰虛,,,,
舌紅,舌形胖,熱,痰,溼,血熱,
舌絳,,血熱,熱,陰虛,亡陰,
舌白,,血虛,陽虛,氣虛,氣陷,
舌白,舌形胖,陽虛,寒,溼,氣虛,
舌紫,,陽虛,血瘀,痰,,