Javascript 右子树中的递归

Javascript 右子树中的递归,javascript,node.js,binary-tree,Javascript,Node.js,Binary Tree,为了更灵活地编写代码,我每天都在尝试解决不同的问题,但到目前为止,这一次阻止了我 5 / \ 3 7 / 1 下面的代码应该在预序遍历中从给定字符串建立一个二叉树。也就是说,下面的二叉树是“5 3 1 N N 7 N N”。元素由空格分隔,N标记为空节点,这些节点为空 5 / \ 3 7

为了更灵活地编写代码,我每天都在尝试解决不同的问题,但到目前为止,这一次阻止了我

             5
            / \
          3     7
         /
        1
下面的代码应该在预序遍历中从给定字符串建立一个二叉树。也就是说,下面的二叉树是“5 3 1 N N 7 N N”。元素由空格分隔,N标记为空节点,这些节点为空

             5
            / \
          3     7
         /
        1
它应该像遍历拆分字符串一样简单,当找到除
“N”
以外的其他内容时,将使用该值构造一个
节点
,并增加
索引

             5
            / \
          3     7
         /
        1
索引增加后,我再次将下一个数组元素放入左子树。如果遇到
“N”
,则无需执行任何操作,因为
节点的构造函数的左子项已设置为null,因此我只增加
索引。理论上,右
节点
应该在上一个递归步骤中分配。。。但不知怎的,这失败了

             5
            / \
          3     7
         /
        1
这是因为JavaScript的异步行为吗?我错过了什么

             5
            / \
          3     7
         /
        1
提前感谢您的帮助

             5
            / \
          3     7
         /
        1
class Node {
    constructor(val) {
        this.val = val;
        this.left = this.right = null;
    }
}

class Index {
    constructor() {
        this.index = 0;
    }
    incr() {
        this.index++;
    }
}

function deserialize(treeString) {
    let treeArray = treeString.split(" ");
    let index = new Index();
    let length = treeArray.length;
    function helper(index) {
        if (index.index < length) {
            let node = null;
            if (treeArray[index.index] !== "N") {
                node = new Node(parseInt(treeArray[index.index], 10));
                index.incr();
                node.left = helper(index);
                node.right = helper(index);
            } else {
                index.incr();
            } 
            return node;
        };
    }
    return helper(index);
}
类节点{
构造函数(val){
this.val=val;
this.left=this.right=null;
}
}
类索引{
构造函数(){
该指数=0;
}
增量(){
这个.index++;
}
}
函数反序列化(treeString){
让trearray=treeString.split(“”);
设索引=新索引();
let length=trearray.length;
函数助手(索引){
if(index.index<长度){
设node=null;
如果(树数组[index.index]!=“N”){
node=新节点(parseInt(trearray[index.index],10));
索引incr();
node.left=helper(索引);
node.right=helper(索引);
}否则{
索引incr();
} 
返回节点;
};
}
返回助手(索引);
}

我没有收到您的错误,因为
console.log(JSON.stringify(反序列化('531nn7nn'),null,1))
确实给了我

             5
            / \
          3     7
         /
        1
{
    "val": 5,
    "right": {
        "val": 7,
        "right": null,
        "left": null
    },
    "left": {
        "val": 3,
        "right": null,
        "left": {
            "val": 1,
            "right": null,
            "left": null
        }
    }
}
这似乎是你想要的结果

             5
            / \
          3     7
         /
        1
我们可以做得“简单一点”

             5
            / \
          3     7
         /
        1
  • 防止自己受到无用的伤害
  • 特别是对于递归条件下的停止,最好先编写它们

                 5
                / \
              3     7
             /
            1
    
    function recurse(){
        if (index.index == length) {
            //stop code
            return 
        }
        //your other conditions...
        //your code which will call recurse
    }
    
    2.1此处的“迭代器”是无用的

                 5
                / \
              3     7
             /
            1
    
    由于您仍然依赖于了解自己的结构(Trearray必须“实现”运算符[]),因此获取哑变量至少会减少代码量

                 5
                / \
              3     7
             /
            1
    
    2.2如果您真的想使用迭代器

                 5
                / \
              3     7
             /
            1
    
    您可以看到,无论是在if还是else路径中,您都会增加(这相当于“在trearray中前进”)。所以只需在Trearray上迭代。下面是“流行”元素(主动)

                 5
                / \
              3     7
             /
            1
    
  • 这是因为JavaScripts的异步行为吗
  • 这里实际上没有任何异步代码在运行

                 5
                / \
              3     7
             /
            1
    
    helperinfty = function(){
        while(true){}
    }
    node.left = helperinfty(arr)
    node.right = helper(arr);
    
    您可以观察到,
    node.right=helper(arr)
    从未执行过。当您使用
    setTimeout
    等时,您会得到“时髦”的东西(简单地说,当函数需要回调来同步流时) (答案是否定的)

                 5
                / \
              3     7
             /
            1
    
  • 简化代码
  • 打印与开始时相同的树

                 5
                / \
              3     7
             /
            1
    
    class Node {
        constructor(val) {
            this.val = val;
            this.left = this.right = null;
        }
    }
    
    function deserialize(treeString) {
        let arr = treeString.split(" ");
        function helper(arr) {
            if(arr.length == 0)return null;//note that in previous implem helper "could" return undefined...which is not something desired
            let current = arr.shift();
            if (current == "N"){
                //this is a matter of preference. Arguably one can prefer your style.
                //I prefer to emphase that when N is found it is meant to be a null node, and "abort" any recursion
                return null
            }
            let node = new Node(parseInt(current, 10));
            node.left = helper(arr);
            node.right = helper(arr);
            return node;
        }
        return helper(arr);
    }
    x = deserialize('5 3 1 N N N 7 N N');
    console.log(JSON.stringify(x, null, 4))
    

    我没有收到您的错误,因为
    console.log(JSON.stringify(反序列化('531nn7nn'),null,1))
    确实给了我

                 5
                / \
              3     7
             /
            1
    
    {
        "val": 5,
        "right": {
            "val": 7,
            "right": null,
            "left": null
        },
        "left": {
            "val": 3,
            "right": null,
            "left": {
                "val": 1,
                "right": null,
                "left": null
            }
        }
    }
    
    这似乎是你想要的结果

                 5
                / \
              3     7
             /
            1
    
    我们可以做得“简单一点”

                 5
                / \
              3     7
             /
            1
    
  • 防止自己受到无用的伤害
  • 特别是对于递归条件下的停止,最好先编写它们

                 5
                / \
              3     7
             /
            1
    
    function recurse(){
        if (index.index == length) {
            //stop code
            return 
        }
        //your other conditions...
        //your code which will call recurse
    }
    
    2.1此处的“迭代器”是无用的

                 5
                / \
              3     7
             /
            1
    
    由于您仍然依赖于了解自己的结构(Trearray必须“实现”运算符[]),因此获取哑变量至少会减少代码量

                 5
                / \
              3     7
             /
            1
    
    2.2如果您真的想使用迭代器

                 5
                / \
              3     7
             /
            1
    
    您可以看到,无论是在if还是else路径中,您都会增加(这相当于“trearray中的advance”)。因此,只需在trearray上迭代即可。下面是“pop”元素(向前)

                 5
                / \
              3     7
             /
            1
    
  • 这是因为JavaScripts的异步行为吗 这里实际上没有任何异步代码在运行。如果你提到

                 5
                / \
              3     7
             /
            1
    
    helperinfty = function(){
        while(true){}
    }
    node.left = helperinfty(arr)
    node.right = helper(arr);
    
    您可以观察到,
    node.right=helper(arr)
    从未执行过。当您使用
    setTimeout
    等时,您会得到“时髦”的东西(简单地说,当函数需要回调来同步流时) (答案是否定的)

                 5
                / \
              3     7
             /
            1
    
  • 简化代码
  • 打印与开始时相同的树

                 5
                / \
              3     7
             /
            1
    
    class Node {
        constructor(val) {
            this.val = val;
            this.left = this.right = null;
        }
    }
    
    function deserialize(treeString) {
        let arr = treeString.split(" ");
        function helper(arr) {
            if(arr.length == 0)return null;//note that in previous implem helper "could" return undefined...which is not something desired
            let current = arr.shift();
            if (current == "N"){
                //this is a matter of preference. Arguably one can prefer your style.
                //I prefer to emphase that when N is found it is meant to be a null node, and "abort" any recursion
                return null
            }
            let node = new Node(parseInt(current, 10));
            node.left = helper(arr);
            node.right = helper(arr);
            return node;
        }
        return helper(arr);
    }
    x = deserialize('5 3 1 N N N 7 N N');
    console.log(JSON.stringify(x, null, 4))
    

    如果一层一层地走,你确定要先走左边吗?在这种情况下,它将是[5,3,7,1],仅此而已。我相当确定,在预序遍历中,应该首先在左子树上递归,是的。也可以使用级别/宽度一阶、后阶或顺序遍历……在本例中,您希望使用前阶。问题在于从给定的字符串构造树。如果逐级执行,是否确实要先执行左侧操作?在这种情况下,它将是[5,3,7,1],仅此而已。我相当确定,在预序遍历中,应该首先在左子树上递归,是的。也可以使用级别/宽度一阶、后阶或顺序遍历……在本例中,您希望使用前阶。问题在于从给定字符串构造树。非常感谢您提供的详细答案!我真的把自己搞糊涂了,我写的单元测试不断告诉我事情完全错了,这是因为我尝试了一个依赖于树是BST的实现-所以测试输入字符串中没有N,但是有序值-当然,结果是一个扩展的二叉树,由于缺少对长度为0的数组的检查,右子树中未定义。使用array.shift()并将剩余的数组放入下一个递归调用比使用我的索引解决方案更聪明,非常感谢!非常感谢您的详细回答!我真的把自己搞糊涂了,联合体