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

将递归JS函数addWidths转换为迭代实现的技术求助

递归转迭代:实现addWidths函数的非递归版本

我编写了如下递归JS函数addWidths,它接收一个由嵌套节点组成的参数node,通过为每个节点添加其所有叶子节点总数(非仅直接子节点)的width属性来修改原节点:

const addWidths = (node) => {
    const keys = Object.keys(node)
    for(const key of keys){
        addWidths(node[key])
    }
    if(keys.length > 0){
        node["width"] = Object.values(node).reduce((acc, cur) => acc + cur["width"], 0)
    }else{
        node["width"] = 1
    }
}

示例输入

const object = {
    "A": {
        "1": {},
        "2": {
            "+": {},
            "-": {}
        },
        "3": {}
    },
    "B": {
        "1": {}
    },
    "C": {},
    "D": {}
}

调用后预期输出

调用addWidths(object)后,对象会被修改为:

{
    "A": {
        "1": {
            "width": 1
        },
        "2": {
            "+": {
                "width": 1
            },
            "-": {
                "width": 1
            },
            "width": 2
        },
        "3": {
            "width": 1
        },
        "width": 4
    },
    "B": {
        "1": {
            "width": 1
        },
        "width": 1
    },
    "C": {
        "width": 1
    },
    "D": {
        "width": 1
    },
    "width":7
}

修改需求

需要将上述递归函数修改为迭代实现。

附:修改后的树形结构及各节点预期width值示意图:
修改后的树形结构


迭代实现方案

递归的核心是利用调用栈完成后序遍历(先处理所有子节点,再处理父节点),迭代版本可以手动模拟栈,记录每个节点的访问状态:

const addWidthsIterative = (node) => {
    // 栈元素格式:[当前节点, 是否已处理过子节点]
    const stack = [[node, false]];

    while (stack.length > 0) {
        const [currentNode, isProcessed] = stack.pop();

        if (!isProcessed) {
            // 第一次弹出,标记为待处理后重新入栈
            stack.push([currentNode, true]);
            // 子节点逆序入栈,保证处理顺序和递归逻辑一致
            const childKeys = Object.keys(currentNode);
            for (let i = childKeys.length - 1; i >= 0; i--) {
                stack.push([currentNode[childKeys[i]], false]);
            }
        } else {
            // 第二次弹出,所有子节点已处理完成,计算当前节点width
            const childValues = Object.values(currentNode);
            currentNode.width = childValues.length === 0 
                ? 1 
                : childValues.reduce((acc, child) => acc + child.width, 0);
        }
    }
};

代码说明

  • 用栈存储节点和处理状态:isProcessed为false时,该节点的子节点尚未处理;为true时,所有子节点已处理完毕,可计算当前节点的width。
  • 首次弹出未处理节点时,先标记为待处理重新入栈,再将子节点逆序入栈,确保子节点的处理顺序和递归逻辑一致。
  • 节点标记为已处理时,直接根据子节点的width求和,叶子节点直接设为1。

测试该迭代函数,传入示例输入后,输出结果与递归版本完全一致。


内容的提问来源于stack exchange,提问作者Axel Carré

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 11:20:35