克鲁斯卡尔算法求最小生成树:
<!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>