右子树中的递归

时间:2018-06-26 08:01:26

标签: javascript node.js binary-tree

为了使代码编写变得更加灵活,我每天都在尝试解决不同的问题,但是到目前为止,这仍然使我停滞不前。

下面的代码应该在preOrder遍历中根据给定的String构建一个二叉树。即,以下二进制树为“ 5 3 1 N N N 7 N N”。元素由空格分隔,N标记为空节点,它们只是空。

             5
            / \
          3     7
         /
        1

它应该像遍历拆分后的字符串一样简单,并且当发现"N"以外的其他内容时,将使用该值构造一个Node,并增加Index

增加index之后,我再次将下一个数组元素放入左侧子树中。如果遇到"N",则不需要做任何事情,因为node的构造函数已经将左子级设置为null,因此我只增加了index。从理论上讲,应该在上一个递归步骤中分配正确的node……但是以某种方式失败了?

是因为JavaScript的异步行为吗?我想念什么?

预先感谢您的帮助!

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);
}

1 个答案:

答案 0 :(得分:3)

我没听错,因为console.log(JSON.stringify(deserialize('5 3 1 N N N 7 N N'),null,1))确实给了我

{
    "val": 5,
    "right": {
        "val": 7,
        "right": null,
        "left": null
    },
    "left": {
        "val": 3,
        "right": null,
        "left": {
            "val": 1,
            "right": null,
            "left": null
        }
    }
}

这似乎是您预期的结果

我们可以做些“简单”

  1. 防止无用的缩进

特别是对于递归条件下的停止,最佳做法是先编写它们

function recurse(){
    if (index.index == length) {
        //stop code
        return 
    }
    //your other conditions...
    //your code which will call recurse
}

2.1这里的“迭代器”没用

由于您仍然依赖于了解自己的结构(treeArray 必须“实现”运算符[]),因此使用哑变量至少会减少代码量

2.2如果您真的要使用迭代器

您会看到,无论在您的if还是else路径中,都增加了incr(这等效于“ advance in treeArray”)。因此,只需遍历treeArray。下面我们“向前”弹出“元素”

function helper(arr){
    if end
        return
    let currentNodeVal = arr.shift() //advance in treeArray
    if (currentNodeVal !== "N") {
        node = new Node(parseInt(currentNodeVal, 10));
        node.left = helper(arr);
        node.right = helper(arr);
    } else {
        //nothing to do
    } 
}
  1. 是因为JavaScript的异步行为吗?

在这里,您实际上没有任何异步代码在运行。如果您命名

helperinfty = function(){
    while(true){}
}
node.left = helperinfty(arr)
node.right = helper(arr);

您会发现node.right = helper(arr)从未执行。使用setTimeout等时,您会得到“笨拙”的东西(仅当函数需要回调来同步流时才放入) (答案是否定的)

  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))