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

修复Fortran二叉树递归子程序仅左节点赋值问题

递归构建表达式二叉树的问题

我需要通过递归方式构建二叉树,具体需求如下:

  • 创建带左右子节点的根节点
  • 从根节点派生不同值,分别赋值给左右子节点
  • 对左右子节点重复上述操作,持续递归扩展节点

但当前程序仅能为左节点赋值和插入节点,我清楚问题根源但不知道如何修正,希望实现递归时能同时处理左右子节点。输入为形如((3*(4+7)):((4+2)*(3-1)))的表达式(始终包含外层括号)。

现有代码

二叉树类型定义

type tree
    character(len=80)::expression
    type(tree), pointer::left,right
end type tree

递归拆分的核心子例程

recursive subroutine split(str)

    character(len=80):: str
    type(tree),pointer:: point
  
    allocate(point)
    point%expression = str

    call find_bracket(point%expression)
       
    if(found_bracket) then           ! 查找右括号")"
        allocate(point%left)
        allocate(point%right)

        call find_zero_niveau(str)  
        call empty_slots(str)

        ! 赋值新的表达式内容
        point%left%expression = str(2 : zero_niv - 2)                
        point%right%expression = str(zero_niv  : 80 - spaces - 1)
        point%expression = str(zero_niv - 1 : zero_niv - 1 )

        ! 这里的指针操作错误,导致无法正确访问根节点的右子节点
        point => point%left
        call split(point%expression)

        point => point%right            
        call split(point%expression)          ! 这显然无法正常工作
    end if 

end subroutine split

辅助子例程:查找括号层级为0的位置

subroutine find_zero_niveau(str)

    character(len=80)::str
    integer::j, bracket_niv
    logical::bracket_check = .false.

    call empty_slots(str)

    j = 80 - spaces                     
    bracket_niv = 0

    do while (j >= 1)  
        j = j - 1
        call getnextchar(str,j)

        if (next_char == ")") then
            bracket_check = .true.
            bracket_niv = bracket_niv + 1
        else if (next_char == "(") then
            bracket_niv = bracket_niv - 1
        end if

        if (bracket_niv == 0 .and. bracket_check) then
            zero_niv = j
            exit
        end if
    end do

end subroutine find_zero_niveau

辅助子例程:统计末尾空格数

subroutine empty_slots(str)

    character(len=80)::str
    integer::i 

    spaces = 0

    do i=1,80
        call getnextchar(str,i) ! 从字符串中提取指定位置的字符
        if (next_char == " ") then
            spaces = spaces + 1
        else if (next_char /= " ") then
            spaces = 0
        end if
    end do

end subroutine empty_slots

问题分析与修正

问题出在指针的重新赋值上:当执行point => point%left后,原来指向当前根节点的point指针已经被替换为指向左子节点,后续的point => point%right实际是在访问左子节点的右指针,而非最初根节点的右子节点,自然无法正确处理右子树的递归构建。

修正方法很简单:直接使用根节点的left和right指针来调用递归,不要修改原来的point指针。同时建议新增输出参数明确返回构建的节点,避免内部指针混乱,修改后的split子例程如下:

recursive subroutine split(str, node)
    ! 新增node参数,返回构建好的节点,避免内部指针的混乱
    character(len=80):: str
    type(tree), pointer:: node
  
    allocate(node)
    node%expression = str

    call find_bracket(node%expression)
       
    if(found_bracket) then           
        allocate(node%left)
        allocate(node%right)

        call find_zero_niveau(str)  
        call empty_slots(str)

        node%left%expression = str(2 : zero_niv - 2)                
        node%right%expression = str(zero_niv  : 80 - spaces - 1)
        node%expression = str(zero_niv - 1 : zero_niv - 1 )

        ! 直接对左右子节点递归调用,不修改当前node指针
        call split(node%left%expression, node%left)
        call split(node%right%expression, node%right)
    end if 

end subroutine split

调用时只需声明指针变量并传入:

type(tree), pointer:: root
call split(input_str, root)

这样就能同时递归处理左右子节点,正确构建出完整的表达式二叉树。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 06:35:10