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>
克鲁斯卡尔算法
版权声明:本文为lanshanxiao原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。