为何我的K-dimensional树渲染异常?Python anytree技术问询
问题描述
使用Python的anytree包创建并展示K-dimensional树,但树无法正常渲染。预期[4 7]与[17 16]节点处于同一层级,但实际渲染结果不符合预期。
节点类源码
import numpy as np from anytree import NodeMixin class KdData: def __init__(self) -> None: self.key = None class KdNode(KdData, NodeMixin): def __init__(self, parent=None, children=None, axis: int = 0) -> None: super().__init__() self.axis = axis self.parent = parent if children: self.children = children def set_key(self, key): self.key = np.array(key) if self.key is not None: self.children = [ KdNode(axis=(self.axis + 1) % self.key.shape[0]), KdNode(axis=(self.axis + 1) % self.key.shape[0]) ] def get_left_node(self): if self.key is None: return None return self.children[0] def get_right_node(self): if self.key is None: return None return self.children[1] def insert(self, key): if self.key is None: self.set_key(key) elif key[self.axis] < self.key[self.axis]: self.get_left_node().insert(key) else: self.get_right_node().insert(key) # Other functions are omitted because it's not relavant to the question
树创建代码
tree = KdNode() tree.set_key(np.array([5,6])) tree.insert([4,7]) tree.insert([17,16]) tree.insert([7,8]) tree.insert([1,4]) tree.insert([9,13])
导出器代码
def node_attribute(node): att = "" att += "shape=plaintext" return att def edge_att(source, target): att = "" if target.key is None: att += "style=invis" return att from anytree.exporter.dotexporter import DotExporter, UniqueDotExporter dot_obj = UniqueDotExporter(tree, nodenamefunc=lambda node: node.key if node.key is not None else "", nodeattrfunc=lambda node: node_attribute(node), edgeattrfunc=lambda src, tgt: edge_att(src, tgt))
原因与解决方案
核心问题
- 节点名格式错误:numpy数组的字符串表示(如
[5 6])包含空格和方括号,在Dot语言中这类带特殊字符的节点名必须用引号包裹,否则会被解析器错误识别,导致树结构渲染混乱。 - 空节点未完全隐藏:当前仅隐藏了指向空节点的边,但空节点本身仍会显示为空白节点,干扰树的视觉层级判断。
修改后的导出器代码
def node_attribute(node): att = "shape=plaintext" # 完全隐藏空节点 if node.key is None: att += ", style=invis" return att def edge_att(source, target): att = "" if target.key is None: att += "style=invis" return att from anytree.exporter.dotexporter import UniqueDotExporter dot_obj = UniqueDotExporter(tree, # 给节点名添加引号,避免特殊字符解析错误 nodenamefunc=lambda node: f'"{node.key}"' if node.key is not None else '""', nodeattrfunc=lambda node: node_attribute(node), edgeattrfunc=lambda src, tgt: edge_att(src, tgt))
验证
修改后,Dot解析器能正确识别每个节点的名称,空节点也会被完全隐藏,渲染出的树结构中[4 7]与[17 16]会处于同一层级,符合Kd树的插入逻辑。
内容的提问来源于stack exchange,提问作者Nguyễn Tiến Đạt
相关产品推荐
相关产品推荐

