求最小生成树的两种算法:普利姆算法(加点法)& 克鲁斯卡尔算法(加边法)
普利姆算法(加点法)
逻辑:
1)任选一个点为起点
2)找到以当前节点为起点路径最短的边
3)如果这个边另一端没有被连通,那么就链接
4)如果这个边的另一端已经被连通,则看倒数第二短的边
5)重复2-4的步骤,将所有的点连通为止
有A、B、C、D、E 5个村庄,它们之间的距离如图示:
最小生成树如下图:
var MAX_DISTANCE = 1000000;
var pointSet = ["A", "B", "C", "D", "E"];
var distance = [
[0, 4, 7, MAX_DISTANCE, MAX_DISTANCE],
[4, 0, 8, 6, MAX_DISTANCE],
[7, 8, 0, 5, MAX_DISTANCE],
[MAX_DISTANCE, 6, 5, 0, 7],
[MAX_DISTANCE, MAX_DISTANCE, MAX_DISTANCE, 7, 0],
];
class Node {
constructor(val) {
this.val = val;
this.neighbor = [];
}
}
let pointList = new Array(pointSet.length)
.fill("0")
.map((item, index) => new Node(pointSet[index]));
/**
*
* @param {*} nodeList 节点的集合
* @param {*} distanceList距离的集合
* @param {*} startNode 起点节点
*/
function prim(nodeList, distanceList, startNode) {
let visitedNode = [startNode];
while (visitedNode.length < nodeList.length) {
let minDisNode = getMiniDisNode(nodeList, distanceList, visitedNode);
visitedNode.push(minDisNode);
}
}
/**
* 根据已连通的节点返回该节点在原节点集合中的位置
* @param {*} nodeList
* @param {*} node
* @returns
*/
function getIndex(nodeList, node) {
return nodeList.indexOf(node);
}
/**
*
* @param {*} nodeList 原节点集合
* @param {*} distanceList距离集合
* @param {*} visitedList 已连通的节点集合
* @returns
*/
function getMiniDisNode(nodeList, distanceList, visitedList) {
let minDis = MAX_DISTANCE;
let visitedNode = null;
let minDisNode = null;
//遍历已连通的节点,在未连通的节点中找出与已连通的节点距离最近的节点
for (let i = 0; i < visitedList.length; i++) {
//找到已连通的节点在原节点集合中的位置
let index = getIndex(nodeList, visitedList[i]);
for (let j = 0; j < distanceList[index].length; j++) {
if (
visitedList.indexOf(nodeList[j]) < 0 &&
distanceList[index][j] < minDis
) {
minDis = distanceList[index][j];
visitedNode = visitedList[i];
minDisNode = nodeList[j];
}
}
}
visitedNode.neighbor.push(minDisNode);
minDisNode.neighbor.push(visitedNode);
return minDisNode;
}
prim(pointList, distance, pointList[0]);
console.log(pointList);