如何在Python控制台以ASCII格式打印双向链表节点树
哇,作为刚学编程的高中生能自己实现树形结构的插入逻辑,这已经很厉害了!我来帮你搞定ASCII格式打印的问题~
解决思路:树形结构的ASCII打印
首先,明确你的核心需求:把基于双向链表的节点树,转换成你给出的垂直/水平ASCII艺术格式。打印树形结构的核心是遍历节点+控制排版,我们分两种格式来实现:
一、水平格式打印(类似你第一个示例)
这种是最常见的树形打印方式,用递归的深度优先遍历(DFS)处理每个节点,同时维护一个prefix字符串记录当前分支的线条,确保子节点排版正确。
实现步骤:
- 先遍历右子树,再打印当前节点,最后遍历左子树(让树从左到右自然展开)
- 用
prefix控制分支线:左子节点在父节点分支后留白,右子节点保留竖线表示同一分支
代码修改(整合到你的现有代码中):
class node: def __init__(self, value = None): self.value = value self.leftChild = None self.rightChild = None self.leftParent = None self.rightParent = None class node_control: def __init__(self): self.root = None def insert(self, value): if self.root != None: self._insert(value, self.root) return else: print("New root - None", value) self.root = node(value) def _insert(self, value, cur_node): #Go down right side while cur_node.rightChild != None and cur_node.rightChild.value != "@": print("ran") cur_node = cur_node.rightChild #If no right child if cur_node.rightChild == None: print("New node on right - None", value, "-", cur_node.value) #Create new node cur_node.rightChild = node(value) cur_node.rightChild.leftParent = cur_node return #If there is a "@" else: rep = True while rep: print(cur_node.value) #Check left child if cur_node.leftChild == None: print("New node - No left child", value, "-", cur_node.value) rep = False cur_node.leftChild = node(value) cur_node.leftChild.rightParent = cur_node return elif cur_node.leftChild.value == "@": #If left child is blocked if cur_node.leftParent != None: print("Left is blocked", value, "-", cur_node.value) print("Parent: ", cur_node.leftParent.value) cur_node = cur_node.leftParent rep = True continue elif cur_node.rightParent != None: cur_node = cur_node.rightParent.leftParent rep = True continue else: #Must have a non "@" value so go down that line print("Left is clear, reset", value, "-", cur_node.leftChild.value) self._insert(value, cur_node.leftChild) return # 添加水平打印方法 def print_horizontal(self): def _print(node, prefix="", is_left=True): if node is None: return # 先打印右子树 _print(node.rightChild, prefix + ("│ " if is_left else " "), False) # 打印当前节点 print(f"{prefix}{'└── ' if is_left else '┌── '}{node.value}") # 再打印左子树 _print(node.leftChild, prefix + (" " if is_left else "│ "), True) _print(self.root) # 测试代码 tree = node_control() text_code = "ABC@@DE@@@F@@" text_array = list(text_code) print(text_array) for char in text_array: tree.insert(char) print("\n\n水平格式打印:") tree.print_horizontal()
效果说明:
运行后会输出类似你第一个示例的水平树形,│表示同一分支的竖线,└──/┌──表示节点的连接,结构清晰直观。
二、垂直格式打印(类似你第二个示例)
垂直格式相当于把水平树旋转90度,需要先把每个节点映射到二维数组的对应位置,再逐行打印。核心是计算节点的深度和横向偏移,避免重叠。
实现步骤:
- 计算树的最大深度,确定二维数组的大小
- 递归填充数组:根节点放在中间,左子树向上偏移,右子树向下偏移
- 逐行打印数组内容
代码修改(在node_control类中添加):
# 添加垂直打印方法 def print_vertical(self): if self.root is None: return # 辅助函数:计算树的最大深度 def get_max_depth(node): if node is None: return 0 return 1 + max(get_max_depth(node.leftChild), get_max_depth(node.rightChild)) max_depth = get_max_depth(self.root) # 初始化二维布局,宽度为2*max_depth+1(确保左右有足够空间) layout = [] # 辅助函数:填充二维布局 def fill_layout(node, depth, pos): if node is None: return # 如果当前深度的行不存在,创建一行空格 while depth >= len(layout): layout.append([" "]*(2*max_depth +1)) # 把当前节点放到对应位置 layout[depth][pos] = node.value # 左子树:深度减1,位置减1(对应垂直方向的上方) fill_layout(node.leftChild, depth-1, pos-1) # 右子树:深度加1,位置加1(对应垂直方向的下方) fill_layout(node.rightChild, depth+1, pos+1) # 根节点放在中间位置(深度为max_depth,位置为max_depth) fill_layout(self.root, max_depth, max_depth) # 打印每一行 print("\n垂直格式打印:") for line in layout: print("".join(line))
然后在测试代码末尾添加:
tree.print_vertical()
效果说明:
运行后会生成类似你第二个示例的垂直树形结构,空白区域用空格填充,节点位置对应树的层级关系。
小提示:关于@节点
从你的代码和期望输出看,@是作为叶子节点存在的,上面的打印函数会正常打印它。如果之后想隐藏@节点,只需要在递归函数里加判断:if node.value == "@": return,就能跳过@节点的打印。
内容的提问来源于stack exchange,提问作者Moses Wescombe
相关产品推荐
相关产品推荐

