迪杰斯特拉是对顶点进行操作,适合稠密图,大致思想就是选定一个源点,dis数组记录的就是这个源头到各个顶点间的距离,还没进行迪杰斯特拉之前,dis其实就是邻接矩阵中的其中一行,然后进行迪杰斯特拉,先找到离这个源头最近的顶点k,将其标记,并且以这个点为中间点,看有没有别的顶点通过这个顶点k到源点的距离比dis记录的要小,如果有就更新。
关于创建邻接矩阵的部分这里就不多说了,前面我写的博客有讲解。
import java.util.Arrays;
import java.util.Scanner;
public class test {
static int VexNums=0;
static int edgeNums=0;
static int[] VexArr=null;
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
System.out.println("请输入顶点数和边数");
VexNums=scanner.nextInt();
edgeNums=scanner.nextInt();
VexArr=new int[VexNums];
System.out.println("请输入顶点信息");
for(int i=0;i<VexNums;i++) {
VexArr[i]=scanner.nextInt();
}
int[][] graph=new int[VexNums][VexNums];
createGraph(graph);//创建图
int[] dis=new int[VexNums];
dijkstra(graph, dis);
int sum=0;
for(int i=0;i<VexNums;i++) {
System.out.print(dis[i]+" ");
sum+=dis[i];
}
System.out.println("");
System.out.println(sum);
}
public static void createGraph(int[][] graph) {
Scanner scanner=new Scanner(System.in);
int inf=Integer.MAX_VALUE-1234356;
//初始化邻接矩阵
for(int i=0;i<VexNums;i++) {
for(int j=0;j<VexNums;j++) {
if(i==j) {
graph[i][j]=0;
}
else graph[i][j]=inf;
}
}
//输入边的信息
for(int i=0;i<edgeNums;i++) {
System.out.println("请输入相邻的边及权值");
int begin=scanner.nextInt();
int over=scanner.nextInt();
int indexBegin=getIndex(begin);
int indexOver=getIndex(over);
int weight=scanner.nextInt();
//有向图
graph[indexBegin][indexOver]=weight;
}
}
//根据值找下标
public static int getIndex(int x) {
//遍历顶点数组,找到数组下标
for(int i=0;i<VexNums;i++) {
if(VexArr[i]==x) {
return i;
}
}
return -1;
}
//就第一个顶点到其预定点的最短路径
public static void dijkstra(int[][] group,int[] dis) {
for(int i=0;i<VexNums;i++) {
//dis[i]表示第一个顶点到i的距离
dis[i]=group[0][i];
}
Boolean[] book=new Boolean[VexNums];
Arrays.fill(book, false);
book[0]=true;//标记一下
//主循环,每次求得第一个顶点到后面的顶点的最短距离
for(int i=1;i<VexNums;i++) {
int k=-1;
int min=Integer.MAX_VALUE-13454432;
//找到离第一个顶点最近的点
for(int j=0;j<VexNums;j++){
if(!book[j]&&dis[j]<min) {
min=dis[j];
k=j;//记录下表
}
}
book[k]=true;//标记这个点,并且以这个点为中间点,看能不能更新其他顶点到第一个顶点的距离
//现在就遍历k,看k相连的
for(int w=0;w<VexNums;w++) {
//如果w没有被遍历过并且第一个顶点到k的距离加上k到w的距离小于原来的第一个顶点到w的距离,则更新
if(!book[w]&&(min+group[k][w])<dis[w]) {
dis[w]=min+group[k][w];
}
}
}
}
}
接下来详细说下迪杰斯特拉的实现过程,先找到离这个源头最近的顶点k,将其标记,并且以这个点为中间点,看有没有别的顶点通过这个顶点k到源点的距离比dis记录的要小,如果有就更新。
//就第一个顶点到其预定点的最短路径
public static void dijkstra(int[][] group,int[] dis) {
for(int i=0;i<VexNums;i++) {
//dis[i]表示第一个顶点到i的距离
dis[i]=group[0][i];
}
Boolean[] book=new Boolean[VexNums];
Arrays.fill(book, false);
book[0]=true;//标记一下
//主循环,每次求得第一个顶点到后面的顶点的最短距离
for(int i=1;i<VexNums;i++) {
int k=-1;
int min=Integer.MAX_VALUE-13454432;
//找到离第一个顶点最近的点
for(int j=0;j<VexNums;j++){
if(!book[j]&&dis[j]<min) {
min=dis[j];
k=j;//记录下表
}
}
//标记这个点,并且以这个点为中间点,看能不能更新其他顶点到第一个顶点的距离
book[k]=true;
//现在就遍历k,看k相连的
for(int w=0;w<VexNums;w++) {
//如果w没有被遍历过
//并且第一个顶点到k的距离加上k到w的距离小于原来的第一个顶点到w的距离
//则更新
if(!book[w]&&(min+group[k][w])<dis[w]) {
dis[w]=min+group[k][w];
}
}
}
我们可以分析出来1-1是0,1-2是1,1-3是3 ,1-4是4,1-5是3,总和就是最后dis数组的和就是11