/*
迪杰斯特拉算法 邻接表
*/
public class Dijkstra {
char[] vertex; //顶点
List<Pair>[] lists; //邻接表
boolean[] visited; //判断此顶点是否已经被标记
int N; //存储顶点的个数
int[] dist; //记录源到其余顶点最短距离
int[] pre; //记录每个结点最短路径中的前驱结点
public Dijkstra(char[] nums){
this.vertex = Arrays.copyOf(nums,nums.length); //初始化顶点
lists = new List[nums.length];
visited = new boolean[nums.length];
this.N = nums.length;
//初始化邻接表
for(int i = 0;i<lists.length;i++){
lists[i] = new ArrayList<>();
}
lists[0].add(new Pair(1,5));
lists[0].add(new Pair(5,2));
lists[0].add(new Pair(2,4));
lists[1].add(new Pair(0,5));
lists[1].add(new Pair(5,1));
lists[1].add(new Pair(4,3));
lists[2].add(new Pair(0,4));
lists[3].add(new Pair(5,4));
lists[3].add(new Pair(4,3));
lists[4].add(new Pair(1,3));
lists[4].add(new Pair(5,2));
lists[4].add(new Pair(3,3));
lists[5].add(new Pair(0,2));
lists[5].add(new Pair(1,1));
lists[5].add(new Pair(4,2));
lists[5].add(new Pair(3,4));
}
public void Dijkstra(int origin){
pre = new int[N]; //表示每个顶点在最短路径中的的前驱顶点
for(int i =0;i<N;i++){ //初始化
pre[i] =-1;
}
dist = new int[N]; //表示源点到其余顶点的最短距离
for(int i = 0;i<N;i++){
if(i==origin){
dist[0] = 0; //自身到自己的距离为0
}else{
dist[i] = Integer.MAX_VALUE; //其余初始为默认值
}
}
visited[origin] = true; //开始的顶点已经被标记
List<Pair> list = lists[origin]; //获取起始顶点直接相连的其他顶点
for(int i = 0;i<list.size();i++){
Pair pair = list.get(i);
dist[pair.getIndex()] = pair.getWeight(); //更新最短距离
pre[pair.getIndex()] = origin; //更新前驱顶点表
}
//开始循环
for(int i = 1;i<N;i++){
//找出dist中除了已经访问过的顶点的最小距离顶点
int minDist = Integer.MAX_VALUE;
int minIndex = -1;
for(int j = 0;j<dist.length;j++){ //遍历dist表
if(!visited[j]&&dist[j]<minDist){ //必须是在未被标记的顶点中选择
minDist = dist[j];
minIndex =j;
}
}
if(minIndex == -1){ //没有找到小于Integer.MAX_VALUE的距离,说明开始的源顶点与其余的顶点都没有相连
return;
}
//开始更新距离和前驱顶点
//拿到minIndex顶点的连接的顶点
List<Pair> list1 = lists[minIndex];
//标记minIndex顶点
visited[minIndex] = true;
//开始遍历
for(int j = 0;j<list1.size();j++){
Pair pair = list1.get(j);
int newDist = minDist + pair.weight; //记录经过该节点到目的结点的距离
if(!visited[pair.getIndex()]&&newDist<dist[pair.getIndex()]){ //必须是在没有被标记的顶点,然后比较
//更新距离和前驱顶点
dist[pair.getIndex()] = newDist;
pre[pair.getIndex()] = minIndex;
}
}
}
}
//展示最短距离
public void showMinDist(){
System.out.println(Arrays.toString(dist));
}
//打印路径
public void getPath(int startIndex,int endIndex){
Stack<Character> stack = new Stack<>();
stack.push(vertex[endIndex]);
int front = pre[endIndex];
while(front!=startIndex){
stack.push(vertex[front]);
front = pre[front];
}
stack.push(vertex[front]);
while(!stack.isEmpty()){
System.out.print(stack.pop()+"-->");
}
}
//Pair对 index:表示顶点在vertex中的索引,weight表示权重
public static class Pair{
int index;
int weight;
public Pair(int index,int weight){
this.index = index;
this.weight = weight;
}
public int getIndex(){
return this.index;
}
public int getWeight(){
return this.weight;
}
}
public static void main(String[] args) {
Dijkstra dijkstra = new Dijkstra(new char[]{'A', 'E', 'F', 'P', 'H', 'G'});
dijkstra.Dijkstra(1);
dijkstra.showMinDist();
int endIndex = 3;
dijkstra.getPath(1,3);
}
}