prim算法是最小生成树算法,它运用的是贪心原理,设置两个点集合,一个集合为要求的生成树的点集合A,另一个集合为未加入生成树的点B。
它的具体实现过程是:
(1):所有的点都在集合B中,A集合为空。
(2):任意以一个点为开始,把这个初始点加入集合A中,从集合B中减去这个点。寻找与它相邻的点中路径最短的点,如后把这个点也加入集合A中,从集合B中减去这个点。
(3):更新未被访问的节点的dist[]值。
(4):重复上述过程。一直到所有的点都在A集合中结束。
Dijkstra是计算最短路径的算法
(1)初始时,S只包含源点v,即S=v。U包含除v外的其他顶点,U中顶点u距离为边上的权(若v与u有边)或(若u不是v的出边邻接点)。
(2)从U中选取一个距离v最小的顶点k,把k,加入S中(该选定的距离就是v到k的最短路径长度)。
(3)以k为新考虑的中间点,修改U中各顶点的距离;若从源点v到顶点u(u U)的距离(经过顶点k)比原来距离(不经过顶点k)短,则修改顶点u的距离值,修改后的距离值的顶点k的距离加上边上的权。
(4)重复步骤(2)和(3)直到所有顶点都包含在S中
代码如下:
package day38;
import java.util.Arrays;
import day31.IntMatrix;
public class Net {
//最大距离
public static final int MAX_DISTANCE = 10000;
//节点数量
int numNodes;
IntMatrix weightMatrix;
/**
* @Description: 构造函数
* @Param: [paraNumNodes]
* @return:
*/
public Net(int paraNumNodes) {
numNodes = paraNumNodes;
weightMatrix = new IntMatrix(numNodes, numNodes);
for (int i = 0; i < numNodes; i++) {
//将所有权值先设为最大距离
Arrays.fill(weightMatrix.getData()[i], MAX_DISTANCE);
}
}
/**
* @Description: 构造函数
* @Param: [paraMatrix]
* @return:
*/
public Net(int[][] paraMatrix) {
weightMatrix = new IntMatrix(paraMatrix);
numNodes = weightMatrix.getRows();
}
@Override
public String toString() {
String resultString = "This is the weight matrix of the graph.\r\n" + weightMatrix;
return resultString;
}
/**
* @Description: 单源最短路径
* @Param: [paraSource(目标节点到每个节点的最短路径)]
* @return: int[]
*/
public int[] shortestPath(int paraSource) {
//初始化
int[] tpDistanceArray = new int[numNodes];
for (int i = 0; i < numNodes; i++) {
tpDistanceArray[i] = weightMatrix.getValue(paraSource, i);
}
int[] tpParentArray = new int[numNodes];
Arrays.fill(tpParentArray, paraSource);
// -1 视为无父节点
tpParentArray[paraSource] = -1;
//已被访问的节点
boolean[] tpVistedArray = new boolean[numNodes];
//表示自己直接跳过
tpVistedArray[paraSource] = true;
//循环找
int tpMinDistance;
int tpBestNode = -1;
for (int i = 0; i < numNodes - 1; i++) {
//找到最优的下一节点
tpMinDistance = Integer.MAX_VALUE;
for (int j = 0; j < numNodes; j++) {
if (tpVistedArray[j]) {
continue;
}
//与每个节点作比较找到最优节点
if (tpMinDistance > tpDistanceArray[j]) {
tpMinDistance = tpDistanceArray[j];
tpBestNode = j;
}
}
tpVistedArray[tpBestNode] = true;
for (int j = 0; j < numNodes; j++) {
if (tpVistedArray[j]) {
continue;
}
//该情况为当前节点未连接到另一节点
if (weightMatrix.getValue(tpBestNode, j) >= MAX_DISTANCE) {
continue;
}
if (tpDistanceArray[j] > tpDistanceArray[tpBestNode]
+ weightMatrix.getValue(tpBestNode, j)) {
tpDistanceArray[j] = tpDistanceArray[tpBestNode]
+ weightMatrix.getValue(tpBestNode, j);
//改变父节点
tpParentArray[j] = tpBestNode;
}
}
//仅作测试
System.out.println("The distance to each node: " + Arrays.toString(tpDistanceArray));
System.out.println("The parent of each node: " + Arrays.toString(tpParentArray));
}
//输出
System.out.println("Finally");
System.out.println("The distance to each node: " + Arrays.toString(tpDistanceArray));
System.out.println("The parent of each node: " + Arrays.toString(tpParentArray));
return tpDistanceArray;
}
/**
* @Description: 普利姆算法
* @Param: []
* @return: int
*/
public int prim() {
//初始化
//任何节点都可以作为起始节点
int tpSource = 0;
int[] tpDistanceArray = new int[numNodes];
for (int i = 0; i < numNodes; i++) {
tpDistanceArray[i] = weightMatrix.getValue(tpSource, i);
}
int[] tpParentArray = new int[numNodes];
Arrays.fill(tpParentArray, tpSource);
tpParentArray[tpSource] = -1;
boolean[] tpVisitedArray = new boolean[numNodes];
tpVisitedArray[tpSource] = true;
int tpMinDistance;
int tpBestNode = -1;
for (int i = 0; i < numNodes - 1; i++) {
tpMinDistance = Integer.MAX_VALUE;
for (int j = 0; j < numNodes; j++) {
if (tpVisitedArray[j]) {
continue;
}
if (tpMinDistance > tpDistanceArray[j]) {
tpMinDistance = tpDistanceArray[j];
tpBestNode = j;
}
}
tpVisitedArray[tpBestNode] = true;
for (int j = 0; j < numNodes; j++) {
if (tpVisitedArray[j]) {
continue;
}
//该情况为当前节点未连接到另一节点
if (weightMatrix.getValue(tpBestNode, j) >= MAX_DISTANCE) {
continue;
}
if (tpDistanceArray[j] > weightMatrix.getValue(tpBestNode, j)) {
tpDistanceArray[j] = weightMatrix.getValue(tpBestNode, j);
//改变父节点
tpParentArray[j] = tpBestNode;
}
}
System.out.println(
"The selected distance for each node: " + Arrays.toString(tpDistanceArray));
System.out.println("The parent of each node: " + Arrays.toString(tpParentArray));
}
int resCost = 0;
for (int i = 0; i < numNodes; i++) {
resCost += tpDistanceArray[i];
}
System.out.println("Finally");
System.out.println("The parent of each node: " + Arrays.toString(tpParentArray));
System.out.println("The total cost: " + resCost);
return resCost;
}
public static void main(String[] args) {
Net tempNet = new Net(3);
System.out.println(tempNet);
int[][] tempMatrix = { { 0, 9, 3, 6 }, { 5, 0, 2, 4 }, { 3, 2, 0, 1 }, { 2, 8, 7, 0 } };
tempNet = new Net(tempMatrix);
System.out.println(tempNet);
tempNet.shortestPath(1);
tempNet.prim();
}
}
运行结果:
This is the weight matrix of the graph.
[[10000, 10000, 10000], [10000, 10000, 10000], [10000, 10000, 10000]]
This is the weight matrix of the graph.
[[0, 9, 3, 6], [5, 0, 2, 4], [3, 2, 0, 1], [2, 8, 7, 0]]
The distance to each node: [5, 0, 2, 3]
The parent of each node: [1, -1, 1, 2]
The distance to each node: [5, 0, 2, 3]
The parent of each node: [1, -1, 1, 2]
The distance to each node: [5, 0, 2, 3]
The parent of each node: [1, -1, 1, 2]
Finally
The distance to each node: [5, 0, 2, 3]
The parent of each node: [1, -1, 1, 2]
The selected distance for each node: [0, 2, 3, 1]
The parent of each node: [-1, 2, 0, 2]
The selected distance for each node: [0, 2, 3, 1]
The parent of each node: [-1, 2, 0, 2]
The selected distance for each node: [0, 2, 3, 1]
The parent of each node: [-1, 2, 0, 2]
Finally
The parent of each node: [-1, 2, 0, 2]
The total cost: 6
注:
1.Prim是计算最小生成树的算法,比如为N个村庄修路,怎么修花销最少。
Dijkstra是计算最短路径的算法,比如从a村庄走到其他任意村庄的距离。
2:Prim算法中有一个统计总len的变量,每次都要把到下一点的距离加到len中;
Dijkstra算法中却没有,只需要把到下一点的距离加到dist[]数组中即可;
3:Prim算法的更新操作更新的dist[]是已访问集合到未访问集合中各点的距离;
Dijkstra算法的更新操作更新的dist[]是源点到未访问集合中各点的距离;