• 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>
    克鲁斯卡尔算法
  • 相关阅读:
    富文本编辑器 ueditor
    防抖和节流 lodash插件
    lodash
    awesome
    怎么在移动端模拟pc端进行web开发调试日志
    添加水印
    node.js取参四种方法req.body,req.params,req.param,req.body
    插件包
    python——Scrapy框架简介、内置选择器、管道文件、爬虫模块中的spider类
    python——BeautifulSoup4解析器,JSON与JsonPATH,多线程爬虫,动态HTML处理
  • 原文地址:https://www.cnblogs.com/lanshanxiao/p/13196179.html
Copyright © 2020-2023  润新知