10.克鲁斯卡尔算法(加边法)求最小生成树(JavaScript版)

克鲁斯卡尔算法求最小生成树:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        function Node(value) {
            this.value = value;
            this.neighbor = [];
            this.distance = [];
        }

        var nodeA = new Node("a");
        var nodeB = new Node("b");
        var nodeC = new Node("c");
        var nodeD = new Node("d");
        var nodeE = new Node("e");
        var nodeF = new Node("f");
        var nodeG = new Node("g");
        var nodeH = new Node("h");

        //存放所有节点的数组
        var pointSet = [nodeA, nodeB, nodeC, nodeD, nodeE, nodeF, nodeG, nodeH];

        var max = Number.POSITIVE_INFINITY; //无穷大

        var distance = [ //点与点之间的距离
            //   a    b    c    d    e    f    g    h
            [0, 1, 2, max, max, max, max, max], //a
            [1, 0, max, 3, max, 5, max, max], //b
            [2, max, 0, 4, max, max, 7, max], //c
            [max, 3, 4, 0, 6, max, max, max], //d
            [max, max, max, 6, 0, 8, 9, max], //e
            [max, 5, max, max, 8, 0, max, 10], //f
            [max, max, 7, max, 9, max, 0, 11], //g
            [max, max, max, max, max, 10, 11, 0] //h
        ];

        //克鲁斯卡尔算法
        function kurskal(pointSet, distance) {
            var resultList = []; //这是一个二维数组,用来存放已连接的部落
            while (true) {
                var begin = null;
                var end = null;
                var minDistance = max;
                for (var i = 0; i < distance.length; i++) {
                    for (var j = 0; j < distance[i].length; j++) {
                        var tempBegin = pointSet[i];
                        var tempEnd = pointSet[j];
                        if (i != j && //自己到自己的距离为0,不能加入
                            distance[i][j] < minDistance && //当前开销小于最小开销
                            canLink(tempBegin, tempEnd, resultList)) { //判断节点是否可以连接
                            begin = tempBegin;
                            end = tempEnd;
                            minDistance = distance[i][j];
                        }
                    }
                }

                link(begin, end, resultList, minDistance); //将最小开销加入
                if (resultList.length == 1 && resultList[0].length == pointSet.length) { //当结果中只有一个部落 && 部落中节点数等于点集合数
                    break;
                }
            }

            console.log(pointSet);
        }

        function canLink(begin, end, resultList) { //判断节点是否可以连接
            var beginIn = null; //存放begin所在的部落
            var endIn = null; //存放end所在的部落
            for (var i = 0; i < resultList.length; i++) { //循环所有部落
                if (resultList[i].indexOf(begin) > -1) { //找到begin所在的部落
                    beginIn = resultList[i];
                }
                if (resultList[i].indexOf(end) > -1) { //找到end所在的部落
                    endIn = resultList[i];
                }
            }
            //1.begin和end都不在部落中----两者可以加入新部落
            //2.begin在A部落,end不在部落中----A部落扩张一个节点
            //3.begin不在部落,end在A部落中----A部落扩张一个节点
            //4.begin在A部落,end在B部落----A和B两个部落可以合并
            //5.begin和end在同一个部落----不能连接
            if (beginIn != null && endIn != null && beginIn == endIn) {
                return false; //满足第5个条件
            }
            return true; //其他条件都是可连接的
        }

        function link(begin, end, resultList, minDistance) { //把节点加入部落
            var beginIn = null; //存放begin所在的部落
            var endIn = null; //存放end所在的部落
            for (var i = 0; i < resultList.length; i++) { //循环所有部落
                if (resultList[i].indexOf(begin) > -1) { //找到begin所在的部落
                    beginIn = resultList[i];
                }
                if (resultList[i].indexOf(end) > -1) { //找到end所在的部落
                    endIn = resultList[i];
                }
            }
            //1.begin和end都不在部落中----两者可以加入新部落
            if (beginIn == null && endIn == null) {
                var newArr = [];
                newArr.push(begin);
                newArr.push(end);
                resultList.push(newArr);
            } else if (beginIn != null && endIn == null) { //2.begin在A部落,end不在部落中----A部落扩张一个节点
                beginIn.push(end);
            } else if (beginIn == null && endIn != null) { //3.begin不在部落,end在A部落中----A部落扩张一个节点
                endIn.push(begin);
            } else if (beginIn != null && endIn != null) { //4.begin在A部落,end在B部落----A和B两个部落可以合并
                beginIn.concat(endIn);
                resultList.slice(resultList.indexOf(endIn), 1); //去除endIn部落
            }
            begin.neighbor.push(end);
            begin.distance.push({
                from: begin,
                to: end,
                distance: minDistance
            });
            end.neighbor.push(begin);
            end.distance.push({
                from: end,
                to: begin,
                distance: minDistance
            });
        }

        kurskal(pointSet, distance);
    </script>
</body>

</html>
克鲁斯卡尔算法

 

posted @ 2020-06-26 19:57  lanshanxiao  阅读(409)  评论(0编辑  收藏  举报