如何避免两次走树

时间:2016-05-14 00:43:58

标签: javascript arrays tree

我有以下方法来初始化树:

function _initTree(treeObj, options){ 
    treeObj = treeObj || []; 
    if(!zpJSUtils.isArray(treeObj)) throw new Error("Input tree must be an array"); 
    this.tree = treeObj; 
    this.rootNode = treeObj[0]; 
    _buildNodes.call(this, treeObj); 
} 

init方法遍历树以将所有对象初始化为节点:

function _buildNodes(treeObj){ 
    traverseTree.call(treeObj, function(nodeObj){
        node = new Node(nodeObj); 
        return true; 
    }, this); 
} 

traverseTree方法(从交换机中选择):

function _walkPreOrder(tree, callback, ctx){ 
    tree.forEach(function(node, idx){ 
        var continueWalk = callback.call(ctx, node); 
        if(continueWalk){
            if(node.hasChildren()){ 
                _walkPreOrder.call(this, node); 
            }; 
        }; 
    }, this); 
}

问题是这个。
我想在init上计算树的高度,这是根节点和叶子之间最长的向下路径上的边数。
所以似乎为了计算高度,我将不得不再次走树(找到最深的嵌套元素的水平)。

json的格式是:

var json = [{ text: "root", children: [
    {id: "id_1", text: "node_1", children:[
        {id: "id_c1", text: "node_c1"}, 
        {id: "id_c2", text: "node_c2", children: [
            {id: "id_c2_c1", text: "node_c2_c1"}, 
            {id: "id_c2_c2", text: "node_c2_c2"}, 
            {id: "id_c2_c3", text: "node_c2_c3"}]},   
        {id: "id_c3", text: "node_c3"}]}, 
    {id: "id_2", text: "node_2"}]}]; 

问题是_walkPreOrder 可以接受多个回调(例如数组),但这会导致一个可疑的api(因为传入多个函数可以继续行走当条件为真/假可疑时树。

解决这个问题的好方法是什么,即避免多次迭代?

1 个答案:

答案 0 :(得分:2)

  1. 在创建子节点时第一次走树时,要么返回或标记每个子节点的最大高度。
  2. 然后在访问所有孩子时,比较所有孩子身高的最大值,然后标记/返回当前节点的数量超过其子女的最大身高。