目录
1.迪杰斯特拉(Dijkstra)算法介绍
2.克鲁斯卡尔最佳实践公交站问题
3.迪杰斯特拉(Dijkstra)算法过程
4.代码实现
迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算-一个节点到其他节点的最
短路径。它的主要特点是以起始点为中心向外层层扩展(广^度优先搜索思想),直到
扩展到终点为止。
1)战争时期,胜利乡有7个村庄(A,B,C,D,E,F,G),现在有六个邮差,从G点出发,需要分别把邮件分别送到A,B,C,D,E,F六个村庄
2)各个村庄的距离用边线表示(权),比如A-B距离5公里
3) 问:如何计算出G村庄到其它各个村庄的最短距离?
4)如果从其它点出 发到各个点的最短距离又是多少?
设置出发顶点为v,顶点集金V{v1,2v.,..},v到V中各顶点的距离构成距离集合Dis,Dis{d1,2,d...},. Dis集 合记录着v到图中各顶点的距离(到自身可以看作0,v到vi距离对应为di)
1)从Dis中选择值最小的di并移出Dis集合,同时移出V集合中对应的顶点vi,此时的v到vi即为最短路径
2)更新Dis集合, 更新规则为:比较v到V集合中项点的距离值, 与v通过vi到V集合中顶点的距离值,保留值较小的一个(同时也应该更新顶点的前驱节点为vi,表明是通过vi到达的)
3) 重复执行两步骤,直到最短路径项点为目标顶点即可结束
package com.example.datastructureandalgorithm.dijkstra;
import java.util.Arrays;
/**
* 迪杰斯特拉算法
*
* @author 浪子傑
* @version 1.0
* @date 2020/6/27
*/
public class DijkstraDemo {
public static void main(String[] args) {
char[] vertex = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
int[][] matrix = new int[vertex.length][vertex.length];
final int N = 65535;
matrix[0] = new int[]{0, 5, 7, N, N, N, 2};
matrix[1] = new int[]{5, 0, N, 9, N, N, 3};
matrix[2] = new int[]{7, N, 0, N, 8, N, N};
matrix[3] = new int[]{N, 9, N, 0, N, 4, N};
matrix[4] = new int[]{N, N, 8, N, 0, 5, 4};
matrix[5] = new int[]{N, N, N, 4, 5, 0, 6};
matrix[6] = new int[]{2, 3, N, N, 4, 6, 0};
Graph graph = new Graph(vertex, matrix);
graph.show();
graph.dsj(6);
graph.showDjs();
}
}
class Graph {
/**
* 存放顶点的数组
*/
private char[] vertex;
/**
* 邻接矩阵
*/
private int[][] matrix;
/**
* 已访问顶点集合
*/
private VisitedVertex visitedVertex;
public Graph(char[] vertex, int[][] matrix) {
this.vertex = vertex;
this.matrix = matrix;
}
public void show() {
for (int[] ints : matrix) {
System.out.println(Arrays.toString(ints));
}
}
public void dsj(int index) {
visitedVertex = new VisitedVertex(vertex.length, index);
update(index);
for (int i = 1; i < vertex.length; i++) {
// 找到新的访问节点
index = visitedVertex.updateArr();
// 继续更新
update(index);
}
}
/**
* 更新index节点到周围节点的距离和前驱节点
*
* @param index
*/
public void update(int index) {
// 循环邻接矩阵
for (int i = 0; i < matrix[index].length; i++) {
// 到第i个节点的距离为,出发顶点到index距离+index到i节点的距离
int length = visitedVertex.getDis(index) + matrix[index][i];
// 和出发顶点到i顶点距离进行比较
if (!visitedVertex.in(i) && length < visitedVertex.getDis(i)) {
visitedVertex.updateDis(i, length);
visitedVertex.updatePre(i, index);
}
}
}
public void showDjs() {
visitedVertex.showDjs();
}
}
//已访问顶点集合
class VisitedVertex {
/**
* 记录各个顶点是否访问过1表示访问过, 0未访问,会动态更新
*/
public int[] already_arr;
/**
* 每个下标对应的值为前- -个顶点下标,会动态更新
*/
public int[] pre_visited;
/**
* 记录出发顶点到其他所有顶点的距离,比如G为出发顶点,
* 就会记录G到其它项点的距离,会动态更新,求的最短距离就会存放到dis|
*/
public int[] dis;
/**
* 构造器
*
* @param length 表示顶点的个数
* @param index 表示出发顶点的下标
*/
public VisitedVertex(int length, int index) {
this.already_arr = new int[length];
this.pre_visited = new int[length];
this.dis = new int[length];
// 初始化dis数组
Arrays.fill(dis, 65535);
// 设置index已经被访问
already_arr[index] = 1;
// 设置出发顶点的访问距离为0
this.dis[index] = 0;
}
/**
* 功能:判断index项点是否被访问过
*
* @param index
* @return 如果访问过, 就返回true, 否则访问false
*/
public boolean in(int index) {
return already_arr[index] == 1;
}
/**
* ※
* 功能:更新出发顶点到index顶点的距离
*
* @param index
* @param len
*/
public void updateDis(int index, int len) {
dis[index] = len;
}
/**
* 功能:更新pre顶点的前驱顶点为index结点
*
* @param pre
* @param index
*/
public void updatePre(int pre, int index) {
pre_visited[pre] = index;
}
/**
* 功能:返回出发顶点到index顶点的距离
*
* @param index
*/
public int getDis(int index) {
return dis[index];
}
/**
* 继续访问并返回新的访问节点
*
* @return
*/
public int updateArr() {
int min = 65535, index = 0;
for (int i = 0; i < already_arr.length; i++) {
if (already_arr[i] == 0 && getDis(i) < min) {
min = getDis(i);
index = i;
}
}
// 更新index已经被访问
already_arr[index] = 1;
return index;
}
public void showDjs() {
char[] vertex = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
int count = 0;
for (int i : dis) {
if (i != 65535) {
System.out.print(vertex[count] + "(" + dis[count] + ")");
} else {
System.out.print(vertex[count] + "(N)");
}
count ++;
}
System.out.println();
}
}