遍历树javascript

时间:2015-11-29 01:50:34

标签: javascript algorithm

我试图在javascript中遍历图表。我的工作是遍历和解析下图的所有可能结果。

This is a rough visualization of the graph 这就是我将图形存储在JS对象中的方式。

var graph = {
    alpha: {
        in: [],
        out: ['a', 'b']
    },
    a: {
        in: ['alpha'],
        out: []
    },
    b: {
        in: ['alpha'],
        out: ['c', 'e']
    },
    c: {
        in: ['b'],
        out: ['d']
    },
    d: {
        in: ['c'],
        out: []
    },
    e: {
        in: ['b'],
        out: ['f', 'g']
    },
    f: {
        in: ['e'],
        out: []
    },
    g: {
        in: ['e'],
        out: []
    }
};

我需要解析它以获得以下输出。

output = [
    ['alpha', 'a'],
    ['alpha', 'b', 'c', 'd'],
    ['alpha', 'b', 'e', 'f'],
    ['alpha', 'b', 'e', 'g']
];

需要注意的关键事项是:

  1. alpha始终是父节点。
  2. 任何节点只能有one输入连接,最多只能有n - 输出连接数
  3. 现在我的方法是使用递归。我只是无法理解它。任何人都可以帮我一把吗?

    var getChild = function (Obj) {
    
        if ( Obj['out'].length == 0){
            console.log('END');
            return
        }else{
            var shifted = Obj['out'].shift();
            console.log(shifted);
            return getChild(graph[shifted]);
        }
    
    }
    

    任何人都可以指导我以最有效的方式遍历图表

2 个答案:

答案 0 :(得分:5)

您可以按照深度优先方式遍历树,如下所示:

var traverse = function(tree, current) {
    //process current node here

    //visit children of current
    for (var cki in current.out) {
        var ck = current.out[cki];
        var child = tree[ck];
        traverse(tree, child);
    }
}

//call on root node
traverse(graph, graph["alpha"]);

[编辑:上面的错误]

但是,树的平面布局有什么特别的原因吗? JS允许您任意嵌套数据,因此您可以拥有

 var graph = {
    alpha: {
        a: {},
        b: {
            c: {
                d: {}
            },
            e: {
                f: {},
                g: {}
            }
        }
    }
}

现在您只处理节点本身,并且您不需要引用。这使得循环(这将破坏上述功能)变得不可能。 要遍历此树,可以将遍历函数简化为仅传递当前节点:

var traverse2 = function(current) {
    //process current node here
    console.log('visiting ' + current);

    //visit children of current
    for (var ck in current) {
        var child = current[ck];
        traverse2(child);
    }
}

//call on root node
traverse(graph);

答案 1 :(得分:0)

仅使用ES5我会坚持图中无循环的保证,并且"解析"使用数组方法:

function pathsFrom(vertex) {
    if (vertex.out.length === 0) return [[vertex]];
    var pathsOfEachChild = vertex.out.map(pathsFrom),
        flatListOfPaths = pathsOfEachChild.reduce(function (flat, branch) {
            return flat.concat(branch);
        }),
        withVertexPrepended = flatListOfPaths.map(function (path) {
            return [vertex].concat(path);
        });
    return withVertexPrepended;
}

进行了一次测试(自由地给了顶点toString)并得到了

[["alpha", "a"], ["alpha", "b", "c", "d"], ["alpha", "b", "e", "f"], ["alpha", "b", "e", "g"]]