You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python控制台以ASCII格式打印双向链表节点树

哇,作为刚学编程的高中生能自己实现树形结构的插入逻辑,这已经很厉害了!我来帮你搞定ASCII格式打印的问题~

解决思路:树形结构的ASCII打印

首先,明确你的核心需求:把基于双向链表的节点树,转换成你给出的垂直/水平ASCII艺术格式。打印树形结构的核心是遍历节点+控制排版,我们分两种格式来实现:


一、水平格式打印(类似你第一个示例)

这种是最常见的树形打印方式,用递归的深度优先遍历(DFS)处理每个节点,同时维护一个prefix字符串记录当前分支的线条,确保子节点排版正确。

实现步骤:

  1. 先遍历右子树,再打印当前节点,最后遍历左子树(让树从左到右自然展开)
  2. 用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度,需要先把每个节点映射到二维数组的对应位置,再逐行打印。核心是计算节点的深度和横向偏移,避免重叠。

实现步骤:

  1. 计算树的最大深度,确定二维数组的大小
  2. 递归填充数组:根节点放在中间,左子树向上偏移,右子树向下偏移
  3. 逐行打印数组内容

代码修改(在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:33:34