Python如何垂直打印真实树形结构,替代现有缩进式树状输出效果
实现思路
你现在的缩进式打印是深度优先遍历逐行输出,要实现带/ \分支的垂直树形结构,需要切换为广度优先逐层打印的逻辑,核心步骤如下:
- 先计算整棵树的最大深度,确定总共有多少层要打印
- 给每个节点分配水平坐标:底层节点从左到右等距排列,父节点坐标位于其所有子节点坐标的中点,保证分支线对齐
- 每层先打印该层所有节点(按计算好的x坐标补空格对齐),再打印下一层的分支连接线(
/\|) - 所有层级打印完成后即可得到你要的树状效果
适配你的类的完整实现代码
class treeNode: def __init__(self,data): self.data = data self.children = [] self.parent = None self.nextSibling = None self.level = 0 self.prevSibling = None self.x = 0 # 新增:存储节点的水平打印坐标 def add_children(self,*child): for i in child: i.parent = self self.children.append(i) if len(self.children) > 1: self.children[-2].nextSibling = i class Tree: def __init__(self,root:treeNode): self.root = root self.depth = 0 self.node_width = 2 # 单个节点占的字符宽度,可根据你的数据调整 self.gap = 2 # 底层节点之间的间隔宽度 # 辅助方法:计算树的最大深度 def get_max_depth(self, node): if not node.children: return 1 max_child_depth = 0 for child in node.children: child_depth = self.get_max_depth(child) if child_depth > max_child_depth: max_child_depth = child_depth return max_child_depth + 1 # 辅助方法:给所有节点分配水平坐标 def assign_x_coords(self, node, depth, left_bound): if not node.children: node.x = left_bound return left_bound + self.node_width + self.gap # 先分配子节点的坐标 child_right_bound = left_bound for child in node.children: child_right_bound = self.assign_x_coords(child, depth+1, child_right_bound) # 父节点坐标在第一个和最后一个子节点的中间 node.x = (node.children[0].x + node.children[-1].x) // 2 return child_right_bound # 重写打印方法 def print_tree(self): self.depth = self.get_max_depth(self.root) self.assign_x_coords(self.root, 0, 0) # 按层遍历节点 current_level = [self.root] for level in range(self.depth): # 第一步:打印当前层的节点 line = [' '] * 200 # 初始化足够长的空行,可根据树的大小调整 for node in current_level: data_str = str(node.data) for i, c in enumerate(data_str): if node.x + i < len(line): line[node.x + i] = c print(''.join(line).rstrip()) # 最后一层不需要打印分支线 if level == self.depth -1: break # 第二步:打印当前层到下一层的分支线 line = [' '] * 200 next_level = [] for node in current_level: next_level.extend(node.children) if len(node.children) == 1: # 只有一个子节点,画竖线 line[node.children[0].x] = '|' elif len(node.children) >=2: # 多个子节点,画左右斜线 left_x = node.children[0].x right_x = node.children[-1].x line[left_x] = '/' line[right_x] = '\\' print(''.join(line).rstrip()) current_level = next_level
测试代码
# 构造你示例里的树 root = treeNode(1) n2 = treeNode(2) n22 = treeNode(22) root.add_children(n2, n22) n3 = treeNode(3) n4 = treeNode(4) n2.add_children(n3, n4) n33 = treeNode(33) n3.add_children(n33) tree = Tree(root) tree.print_tree()
输出效果
1 / \ 2 22 / \ 3 4 | 33
扩展说明
如果需要支持多叉树(每个节点超过2个子节点),只需要修改分支线打印的逻辑,在子节点之间补充横线或者对应连接符号即可。如果节点数据长度不固定,可以动态计算每个节点的宽度调整坐标分配逻辑。
内容的提问来源于stack exchange,提问作者Zakaria Ayadi
相关产品推荐
相关产品推荐

