首页 文章

如何提高在无向图中查找所有循环的性能

提问于
浏览
3

我参考了问题Finding all cycles in undirected graphs . 并写了一个javascript版本,但是我遇到了性能问题,我在chrome上运行,花了大约8秒,太长时间了,在我的无向图上只有16个顶点和33个边 . 这是代码:

<script>
    var graph = [[37,36], [37,168], [37,85], [37,2264], [37,3203], [36,85], [36,536], [36,5097], [85,168], [85,654], [85,755], [85,3607], [85,4021], [85,5097], [168,755], [536,4021], [536,5097], [536,5464], [536,6533], [654,3607], [654,4021], [654,5564], [654,6533], [755,2357], [755,3203], [755,3607], [2264,2357], [2264,3203], [2357,3203], [4021,5097], [5464,5564], [5464,6533], [5564,6533]];
    var cycles = [];

    function findAllCycles() {
        var i, j, len;

        var st1 = new Date().getTime();

        for (i = 0; i < graph.length; i++) {
            var edge = graph[i];
            for (j = 0; j < 2; j++) {
                findNewCycles( [edge[j]] );
            }
        }

        var st2 = new Date().getTime();
        console.log("time: " + (st2-st1));
    };

    function findNewCycles(path) {
        var startNode = path[0],
            nextNode;

        // visit each edge and each node of each edge
        for (var i = 0; i < graph.length; i++) {
            var edge = graph[i];
            for (var j = 0; j < 2; j++) {
                var node = edge[j];
                if (node === startNode) //  edge refers to our current node
                {
                    nextNode = edge[(j + 1) % 2];
                    if ( !visited(nextNode, path) ) { //  neighbor node not on path yet
                        //  explore extended path
                        findNewCycles( [nextNode].concat(path), graph, cycles );
                    }
                    else if ( (path.length > 2) && (nextNode === path[path.length - 1]) ) { //  cycle found
                        //var p = normalize(path);
                        //var inv = invert(p);
                        if ( isNew(path, cycles) ) {
                            cycles.push(path);
                        }
                    }
                }
            }
        }
    }

    // check if vertex n is contained in path
    function visited(node, path) {
        return (path.indexOf(node) !== -1);
    }

    function isNew(path, cycles) {
        for (var i = 0; i < cycles.length; i++) {
            if ( equal(path, cycles[i]) ) {
                return false;
            }
        }

        return true;
    }

    function equal(path1, path2) {
        if (path1.length !== path2.length) {
            return false;
        }

        for (var i = 0; i < path1.length; i++) {
            var node1 = path1[i];
            for (var j = 0; j < path2.length; j++) {
                var node2 = path2[j];
                if (node1 === node2) {
                    break;
                }
            }
            if (j === path2.length) {
                return false;
            }
        }

        return true;
    }

    findAllCycles();
    console.log(cycles);
</script>

我怎样才能提高性能 .

2 回答

  • 0

    我想你可以尝试不同的方式 .

    您可以为每个节点计算它的深度 . 如果你来到一个已经有深度的节点,那么你有一个周期 .

    该算法将在O(n)中,其中n是节点的数量 . 它应该快得多 .

    如果你不关心深度,你可以“标记”节点 .

  • 0

    我认为问题不在于算法的实现 . 这个图表看起来很复杂,显然总共有3930个周期!包括39个无弦循环加上带有和弦的3891个循环(其中包括较小的循环) .

    enter image description here

    这类似于“多少个方块”的问题,它加起来的速度可能会令人惊讶 .

    enter image description here

    如果您只对无弦循环感兴趣,您可以进行显着优化 .

    (旁注:等于函数似乎过于复杂,但这可能不会显着影响性能)

    function pathIsEqual(path1, path2) {
    
        if (path1.length !== path2.length) {
            return false
        }
    
        for(var i = path1.length; i--;) {
            if(path1[i] !== path2[i]){
                return false
            }
        }
    
        return true;
    }
    

相关问题