第 38 天: Dijkstra 算法与 Prim 算法
这两个图的算法当初学数据结构时候感觉遥不可及,现在自己跑一遍发现好像也还行,能写
package datastructures.graph;
import matrix.IntMatrix;
import java.util.Arrays;
/**
* ClassName: Net
* Package: datastructures.graph
* Description: Weighted graphs are called nets.
*
* @Author: luv_x_c
* @Create: 2023/5/29 9:28
*/
public class Net {
/**
* The maximal distance.
*/
public static final int MAX_DISTANCE = 10000;
/**
* The number of nodes.
*/
int numNodes;
/**
* The weight matrix.
*/
IntMatrix weightMatrix;
/**
* The first constructor.
*
* @param paraNumNodes The number of nodes in the graph.
*/
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);
}// Of for i
}//Of the first constructor
/**
* The second constructor
*
* @param paraMatrix The data matrix.
*/
public Net(int[][] paraMatrix) {
weightMatrix = new IntMatrix(paraMatrix);
numNodes = weightMatrix.gerRows();
}// Of the second constructor
@Override
public String toString() {
return " This is the weighted matrix of the graph.\r\n" + weightMatrix;
}// Of toString
/**
* Dijkstra algorithm: shortest path from the source to all nodes.
*
* @param paraSource The source node.
* @return The distance array.
*/
public int[] dijkstra(int paraSource) {
// Step1. Initialize.
int[] tempDistanceArray = new int[numNodes];
for (int i = 0; i < numNodes; i++) {
tempDistanceArray[i] = weightMatrix.getData()[paraSource][i];
}// Of for i
int[] tempParentArray = new int[numNodes];
Arrays.fill(tempParentArray, paraSource);
// -1 for no parent
tempParentArray[paraSource] = -1;
// Visited nodes will not be considered further.
boolean[] tempVisitedArray = new boolean[numNodes];
tempVisitedArray[paraSource] = true;
// Step2. Main loops.
int tempMinDistance;
int tempBestNode = -1;
for (int i = 0; i < numNodes - 1; i++) {
// Step2.1 find the best next node.
tempMinDistance = Integer.MAX_VALUE;
for (int j = 0; j < numNodes; j++) {
//This node is visited.
if (tempVisitedArray[j]) {
continue;
}// Of if
if (tempMinDistance > tempDistanceArray[j]) {
tempMinDistance = tempDistanceArray[j];
tempBestNode = j;
}// Of if
}// Of for j
tempVisitedArray[tempBestNode] = true;
// Step2.2 Prepare for the next round.
for (int j = 0; j < numNodes; j++) {
// This node is visited.
if (tempVisitedArray[j]) {
continue;
}// Of if
// This node cannot reach.
if (weightMatrix.getData()[tempBestNode][j] >= MAX_DISTANCE) {
continue;
}// Of if
if (tempDistanceArray[j] > tempDistanceArray[tempBestNode] + weightMatrix.getData()[tempBestNode][j]) {
// Change distance.
tempDistanceArray[j] = tempDistanceArray[tempBestNode] + weightMatrix.getValue(tempBestNode, j);
// Change parent.
tempParentArray[j] = tempBestNode;
}// Of if
}// Of for j
// For test
System.out.println("The distance to each node :" + Arrays.toString(tempDistanceArray));
System.out.println("The parent of each node :" + Arrays.toString(tempParentArray));
}//Of for i
// Step3. Output for debug.
System.out.println("Finally");
System.out.println("The distance to each node :" + Arrays.toString(tempDistanceArray));
System.out.println("The parent of each node :" + Arrays.toString(tempParentArray));
return tempDistanceArray;
}// Of dijkstra
/**
* The minimal spanning tree.
*
* @return The total cost of the tree.
*/
public int prim() {
// Step1. Initialize.
// Any node can be the source.
int tempSource = 0;
int[] tempDistanceArray = new int[numNodes];
for (int i = 0; i < numNodes; i++) {
tempDistanceArray[i] = weightMatrix.getValue(tempSource, i);
}// Of for i
int[] tempParentArray = new int[numNodes];
Arrays.fill(tempParentArray, tempSource);
//-1 for no parent.
tempParentArray[tempSource] = -1;
// Visited nodes will not be considered further.
boolean[] tempVisitedArray = new boolean[numNodes];
tempVisitedArray[tempSource] = true;
//Step2. Main loops.
int tempMinDistance;
int tempBestNode = -1;
for (int i = 0; i < numNodes - 1; i++) {
// Step2.1 find the best next node.
tempMinDistance = Integer.MAX_VALUE;
for (int j = 0; j < numNodes; j++) {
//This node is visited.
if (tempVisitedArray[j]) {
continue;
}// Of if
if (tempMinDistance > tempDistanceArray[j]) {
tempMinDistance = tempDistanceArray[j];
tempBestNode = j;
}// Of if
}// Of for j
tempVisitedArray[tempBestNode] = true;
// Step2.2 Prepare for the next round.
for (int j = 0; j < numNodes; j++) {
// This node is visited.
if (tempVisitedArray[j]) {
continue;
}// Of if
// This node cannot reach.
if (weightMatrix.getData()[tempBestNode][j] >= MAX_DISTANCE) {
continue;
}// Of if
if (tempDistanceArray[j] > weightMatrix.getData()[tempBestNode][j]) {
// Change distance.
tempDistanceArray[j] = weightMatrix.getValue(tempBestNode, j);
// Change parent.
tempParentArray[j] = tempBestNode;
}// Of if
}// Of for j
// For test
System.out.println("The selected distance for each node: " + Arrays.toString(tempDistanceArray));
System.out.println("The parent of each node: " + Arrays.toString(tempParentArray));
}//Of for i
int resultCost = 0;
for (int i = 0; i < numNodes; i++) {
resultCost += tempDistanceArray[i];
}// Of for i
// Step3. Output for debug.
System.out.println("Finally");
System.out.println("The parent of each node :" + Arrays.toString(tempParentArray));
System.out.println("The total cost :" + resultCost);
return resultCost;
}// Of prim
/**
* The entrance of the program.
*
* @param args Not used now.
*/
public static void main(String[] args) {
Net tempNet0 = new Net(3);
System.out.println(tempNet0);
int[][] tempMatrix = {{0, 9, 3, 6}, {5, 0, 2, 4}, {3, 2, 0, 1}, {2, 8, 7, 0}};
Net tempNet1 = new Net(tempMatrix);
System.out.println(tempNet1);
// Dijkstra
tempNet1.dijkstra(0);
// An undirected net is required.
int[][] tempMatrix2 = {{0, 7, MAX_DISTANCE, 5, MAX_DISTANCE}, {7, 0, 8, 9, 7},
{MAX_DISTANCE, 8, 0, MAX_DISTANCE, 5}, {5, 9, MAX_DISTANCE, 0, 15},
{MAX_DISTANCE, 7, 5, 15, 0}};
Net tempNet2 = new Net(tempMatrix2);
tempNet2.prim();
}// Of main
}// Of class Net
第一遍初始化最小路径的中间变量时候赋值成了MIN_VALUE,prim里面粘贴也是这个,直接异常中断了,还是得细心点,