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

如何在Python中以节点结构形式打印二叉树?附表达式树排序需求

实现数学表达式转有序二叉树并按层打印

嘿,我刚好有一套完整的实现方案,能完美解决你说的把字符串数学表达式转成二叉树,还能保证每个节点的左子节点始终小于右子节点,最后按层级打印的需求。咱们一步步拆解来看:

核心实现步骤

1. 定义二叉树节点类

首先得有个基础的节点结构,用来存储每个元素(操作数或运算符)以及左右子节点:

class TreeNode:
    def __init__(self, value):
        self.value = value
        self.left = None
        self.right = None

2. 构建表达式解析树(buildParseTree)

这个函数负责把字符串形式的数学表达式(带括号、多位数)转换成二叉树结构,核心是用栈来处理括号和运算符优先级:

def buildParseTree(expr):
    # 先清理表达式中的空格
    expr = expr.replace(" ", "")
    stack = []
    current_node = None
    i = 0
    # 定义运算符优先级:*/ 高于 +-
    precedence = {'+':1, '-':1, '*':2, '/':2}

    while i < len(expr):
        char = expr[i]
        # 处理左括号:创建节点并入栈,作为当前节点的父节点
        if char == '(':
            new_node = TreeNode(char)
            if stack:
                parent = stack[-1]
                if not parent.left:
                    parent.left = new_node
                else:
                    parent.right = new_node
            stack.append(new_node)
            current_node = new_node
            i += 1
        # 处理右括号:弹出栈顶,回到父节点层级
        elif char == ')':
            stack.pop()
            current_node = stack[-1] if stack else None
            i += 1
        # 处理多位数操作数
        elif char.isdigit():
            num_str = ""
            while i < len(expr) and expr[i].isdigit():
                num_str += expr[i]
                i += 1
            new_node = TreeNode(int(num_str))
            # 把数字节点挂到当前节点的左/右子节点
            if not current_node.left:
                current_node.left = new_node
            else:
                current_node.right = new_node
        # 处理运算符:根据优先级调整树结构
        elif char in precedence:
            new_node = TreeNode(char)
            # 如果栈顶运算符优先级不低于当前,弹出作为当前节点的父节点
            while stack and stack[-1].value in precedence and precedence[stack[-1].value] >= precedence[char]:
                parent = stack.pop()
                parent.right = new_node
                new_node = parent
            # 把构建好的运算符节点挂到父节点下
            if stack:
                parent = stack[-1]
                if not parent.left:
                    parent.left = new_node
                else:
                    parent.right = new_node
            stack.append(new_node)
            current_node = new_node
            i += 1
    # 栈中最后剩下的就是树的根节点
    return stack[0] if stack else None

3. 节点排序逻辑

这个递归函数会遍历整棵树,确保每个节点的左子节点“小于”右子节点,遵循你提到的规则:

  • 操作数(数字)的优先级低于任何运算符,所以操作数 < 运算符
  • 数字之间直接比较数值大小
  • 运算符之间按优先级比较(*// > +/-)
def sortTreeNodes(node):
    if not node:
        return
    # 先递归排序左右子树
    sortTreeNodes(node.left)
    sortTreeNodes(node.right)

    # 定义节点值的排序权重:数字权重0,运算符按优先级设为1或2
    def get_rank(val):
        if isinstance(val, int):
            return 0
        precedence = {'+':1, '-':1, '*':2, '/':2}
        return precedence.get(val, 0)

    # 判断是否需要交换左右子节点
    if node.left and node.right:
        left_val = node.left.value
        right_val = node.right.value
        left_rank = get_rank(left_val)
        right_rank = get_rank(right_val)
        need_swap = False

        # 情况1:都是数字,左值大于右值则交换
        if isinstance(left_val, int) and isinstance(right_val, int):
            if left_val > right_val:
                need_swap = True
        # 情况2:左是运算符,右是数字,交换(数字更小)
        elif isinstance(left_val, str) and isinstance(right_val, int):
            need_swap = True
        # 情况3:都是运算符,左优先级高于右则交换
        elif isinstance(left_val, str) and isinstance(right_val, str):
            if left_rank > right_rank:
                need_swap = True

        if need_swap:
            node.left, node.right = node.right, node.left

4. 按层级打印树(printNodeInLevels)

用队列实现广度优先遍历,按层输出每个节点的值:

def printNodeInLevels(root):
    if not root:
        print("空树")
        return
    queue = [root]
    while queue:
        level_size = len(queue)
        current_level = []
        for _ in range(level_size):
            node = queue.pop(0)
            current_level.append(str(node.value))
            if node.left:
                queue.append(node.left)
            if node.right:
                queue.append(node.right)
        print(f"Level: {' '.join(current_level)}")

测试示例

咱们用你提到的表达式((2 * 75) / 4)来测试:

# 构建解析树
expr = "((2 * 75) / 4)"
tree_root = buildParseTree(expr)

# 对树节点进行排序
sortTreeNodes(tree_root)

# 按层打印结果
print("按层级排序后的二叉树:")
printNodeInLevels(tree_root)

输出结果

按层级排序后的二叉树:
Level: /
Level: 4 *
Level: 2 75

解释一下结果:原本的根节点/左子节点是*(优先级2),右子节点是4(操作数,权重0),排序后交换了两者的位置;而*的左右子节点2和75已经符合左小右大,所以保持不变。

内容的提问来源于stack exchange,提问作者SriniShine

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 08:59:16