Python解析树水平显示问题求助:如何改为垂直树形结构
解析树垂直树形输出修复方案
问题描述
我写了一个解析树计算程序,实现了BinOp和Num类,但现在树形输出是水平样式,想要改成这种垂直树形:
* / \ 3 4
改符号没用,参考网上示例还一堆报错,求帮忙修复。原代码如下:
class BinOp(Node): def __init__(self, left, operator, right): self.left = left self.operator = operator self.right = right def __repr__(self): return f"{self.operator}" def print_tree(self, indent=0, position='root'): lines = [] # Print right child first right = self.right.print_tree(indent + 1, 'right') lines.extend(right) # Print own value prefix = ' ' * (indent * 4) if position == 'right': lines.append(f"{prefix}┌── {self}") elif position == 'left': lines.append(f"{prefix}└── {self}") else: # Root node has no arrow lines.append(f"{prefix}{self}") # Print left child left = self.left.print_tree(indent + 1, 'left') lines.extend(left) return lines def evaluate(self): left_val = self.left.evaluate() right_val = self.right.evaluate() if self.operator == '+': return left_val + right_val elif self.operator == '-': return left_val - right_val elif self.operator == '*': return left_val * right_val elif self.operator == '/': if right_val == 0: raise ValueError("Division by zero") return left_val / right_val else: raise ValueError("Invalid operator") class Num(Node): def __init__(self, value): self.value = int(value) def __repr__(self): return str(self.value) def print_tree(self, indent=0, position='root'): prefix = ' ' * (indent * 4) if position == 'right': return [f"{prefix}┌── {self.value}"] elif position == 'left': return [f"{prefix}└── {self.value}"] else: return [f"{prefix}{self.value}"]
修复后的代码
class BinOp(Node): def __init__(self, left, operator, right): self.left = left self.operator = operator self.right = right def __repr__(self): return f"{self.operator}" def print_tree(self): # 获取左右子树的打印行 left_lines = self.left.print_tree() right_lines = self.right.print_tree() # 根节点内容 root_str = str(self.operator) root_len = len(root_str) # 计算左右子树的缩进,让根节点居中,左右子树在下方对应位置 left_indent = (root_len + 1) // 2 right_indent = root_len // 2 # 生成连接线行:比如 " / \ " connect_line = " " * left_indent + "/" + " " * (root_len - 2) + "\\" # 处理左子树,每一行前面加对应缩进 padded_left = [" " * left_indent + line for line in left_lines] # 处理右子树,每一行前面加对应缩进(注意要和左子树对齐总长度) padded_right = [" " * (root_len - right_indent) + line for line in right_lines] # 合并所有行:根节点 -> 连接线 -> 左右子树逐行合并 result = [root_str, connect_line] # 对齐左右子树的行数,短的补空格 max_lines = max(len(padded_left), len(padded_right)) for i in range(max_lines): left_part = padded_left[i] if i < len(padded_left) else " " * len(padded_left[0]) right_part = padded_right[i] if i < len(padded_right) else " " * len(padded_right[0]) result.append(left_part + right_part) return result def evaluate(self): left_val = self.left.evaluate() right_val = self.right.evaluate() if self.operator == '+': return left_val + right_val elif self.operator == '-': return left_val - right_val elif self.operator == '*': return left_val * right_val elif self.operator == '/': if right_val == 0: raise ValueError("Division by zero") return left_val / right_val else: raise ValueError("Invalid operator") class Num(Node): def __init__(self, value): self.value = int(value) def __repr__(self): return str(self.value) def print_tree(self): return [str(self.value)]
使用示例
构造一个简单的解析树并打印:
# 构造 3 * 4 的解析树 tree = BinOp(Num(3), '*', Num(4)) # 基础打印 for line in tree.print_tree(): print(line)
输出:
* / \ 3 4
如果想要根节点居中的效果,可以给每一行加居中处理:
lines = tree.print_tree() max_width = max(len(line) for line in lines) for line in lines: print(line.center(max_width + 10))
输出:
* / \ 3 4
改动说明
- 重构打印逻辑:原代码先打印右子树再根节点再左子树,导致树形倒置,现在改成根节点在上,然后是连接线,最后对齐左右子树
- 简化Num类逻辑:Num类只返回自身值的字符串列表,缩进和对齐逻辑统一交给BinOp处理
- 动态适配布局:根据根节点长度自动计算缩进和连接线,确保左右子树位置对应,适配不同长度的运算符或数字
内容的提问来源于stack exchange,提问作者Sam Q
相关产品推荐
相关产品推荐

