单源最短路径
package s23;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
public class ShortestRoute {
private static final int max = Integer.MAX_VALUE;
class Node{ //结点类
Node father;//父节点
int d; //最短路径
private Node(){}
}
private int[][] graph;//有向图二维数组,有边则=权重,无边=max
private char[] arr; //节点字符数组
private List<Node> list; //节点类集合
public ShortestRoute(int[][] graph,char[] arr){
this.graph = graph;
this.arr = arr;
list = new ArrayList<>();
initializeSingleSource();
}
/*单源初始化
源节点为第一个节点,源节点d=0,其他d=max
*/
private void initializeSingleSource(){
for(int i=0;i<graph.length;i++){
Node node = new Node();
node.father = null;
if(i==0)//源节点d=0
node.d=0;
else
node.d=Integer.MAX_VALUE;
list.add(node);
}
}
public boolean dijkstra(){
//dijkstra算法是从源节点开始进行进出栈操作,找出当前出栈结点为起点的所有边,更新终点并进栈,循环操作
Stack<Integer> stack = new Stack<>(); //结点序号栈,先进先出,取每个节点的后续j
stack.push(0);
/*
BellmanFord算法此处不使用进出栈方式而是对每条边进行arr.size()-1次循环
while语句换成如下语句,取消进出栈操作
for(int k = 1; k < arr.size;k++)
for(int i = 1; i < graph.length;i++)
*/
while(!stack.isEmpty()) {
int i = stack.pop(); //出栈
if(graph[i][i] != 0) {
list.clear();
return false;
}
/*
判断是否存在边w(ij),如果存在则判断w(j) > w(ij) + w(i)
如果成立则更新w(j),j的父结点更新为i
j进站
*/
for (int j = 0; j < graph[i].length; j++) {
if(graph[i][j] != 0 && graph[i][j] != max){
if(list.get(j).d > graph[i][j] + list.get(i).d) {
list.get(j).d = graph[i][j] + list.get(i).d;
list.get(j).father = list.get(i);
stack.push(j);
}
}
}
}
//判断是否存在负数的闭环,如果存在则不可能有最大路径
for(int i=0;i<graph.length;i++)
for (int j = 0; j < graph[i].length; j++) {
if(graph[i][j] != 0 && graph[i][j] != max){
if(list.get(j).d > graph[i][j] + list.get(i).d) {
list.clear();
return false;
}
}
}
return true;
}
public void printDijkstra(){
if(list == null || list.size() == 0){
System.out.println("存在路径为负数的闭环");
return;
}
for(int i = 1; i< arr.length; i++){
Node node = list.get(i);
StringBuffer sb = new StringBuffer();
while(node != null){
sb.insert(0,"["+arr[list.indexOf(node)]+":"+node.d+"]");
node = node.father;
if(node!=null)
sb.insert(0,"——");
}
System.out.println(sb);
}
}
public static void main(String[] args) {
int[][] graph = new int[][]{
{0,6,max,max,7},
{max,0,5,-4,8},
{max,-2,0,max,max},
{2,max,7,0,max},
{max,max,-3,9,0}
};
char[] node = {'a','b','c','d','e'};
ShortestRoute route = new ShortestRoute(graph,node);
route.dijkstra();
route.printDijkstra();
}
}
输出
[a:0]——[e:7]——[c:4]——[b:2]
[a:0]——[e:7]——[c:4]
[a:0]——[e:7]——[c:4]——[b:2]——[d:-2]
[a:0]——[e:7]
所有结对最短路径
import java.util.ArrayList;
import java.util.List;
public class AllPairShortestRouter {
private static final int max = Integer.MAX_VALUE;
private int[][] graph;//有向图二维数组,有边则=权重,无边=max
private List<int[][]> dMatrixList; //路径权重矩阵
private List<int[][]> fatherMatrixList; //父节点矩阵
private char[] node; //节点数组
private int[][] finalFatherMatrix; //最终父节点矩阵
private int[][] finalMatrix; //最终路径权重矩阵
public AllPairShortestRouter(int[][] graph,char[] node){
this.graph = graph;
this.node = node;
dMatrixList = new ArrayList<>();
fatherMatrixList = new ArrayList<>();
}
public void floydWarshall(){
if(graph == null && graph.length==0)
return;
dMatrixList.add(graph); //初始权重矩阵
int n = graph.length;
//初始父节点矩阵,没有边的为-1
int[][] fatherMatrix = new int[n][n];
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++){
if(graph[i][j] != 0 && graph[i][j] != max)
fatherMatrix[i][j] = i;
else
fatherMatrix[i][j] = -1;
}
fatherMatrixList.add(fatherMatrix);
/*
每个结对d[ij],循环所有节点作为中间节点的情况
第k个节点作为中间节点,权重矩阵dk‘,父节点矩阵fk’
前一个权重矩阵dk,前一个父节点矩阵fk
dk'[ij] = min(dk[ij], dk[ik] + dk[kj])
如果dk[ij]小,fk'[ij] = fk[ij]
如果 dk[ik] + dk[kj] 小,fk'[ij] = fk[kj]
*/
for(int k = 0; k < n; k++){ //中间节点
int[][] matrix = new int[n][n];
int[][] fMatrix = new int[n][n];
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++){
if(dMatrixList.get(k)[i][j] == max && (dMatrixList.get(k)[i][k]==max || dMatrixList.get(k)[k][j]==max)) {
matrix[i][j] = max;
fMatrix[i][j] = fatherMatrixList.get(k)[i][j];
}
else if(dMatrixList.get(k)[i][j] == max) {
matrix[i][j] = dMatrixList.get(k)[i][k] + dMatrixList.get(k)[k][j];
fMatrix[i][j] = fatherMatrixList.get(k)[k][j];
}
else if(dMatrixList.get(k)[i][k]==max || dMatrixList.get(k)[k][j]==max) {
matrix[i][j] = dMatrixList.get(k)[i][j];
fMatrix[i][j] = fatherMatrixList.get(k)[i][j];
}
else {
matrix[i][j] = Math.min(dMatrixList.get(k)[i][j], dMatrixList.get(k)[i][k] + dMatrixList.get(k)[k][j]);
if (matrix[i][j] < dMatrixList.get(k)[i][j])
fMatrix[i][j] = fatherMatrixList.get(k)[k][j];
else
fMatrix[i][j] = fatherMatrixList.get(k)[i][j];
}
}
dMatrixList.add(matrix);
fatherMatrixList.add(fMatrix);
}
finalFatherMatrix = fatherMatrixList.get(n);
finalMatrix = dMatrixList.get(n);
}
public void print(int i,int j){
if(finalFatherMatrix == null || finalFatherMatrix.length == 0)
return;
if(i==j)
System.out.print(node[i]);
else if(finalFatherMatrix[i][j] == -1)
System.out.println("没有路径");
else {
print(i,finalFatherMatrix[i][j]);
System.out.print(node[j]);
}
}
public static void main(String[] args) {
int[][] graph = new int[][]{
{0,6,max,max,7},
{max,0,5,-4,8},
{max,-2,0,max,max},
{2,max,7,0,max},
{max,max,-3,9,0}
};
char[] node = {'a','b','c','d','e'};
AllPairShortestRouter route = new AllPairShortestRouter(graph,node);
route.floydWarshall();
route.print(0,3);
}
}