最短路径:迪杰斯特拉算法

简介

        英文名Dijkstra

        作用:找到路中指定起点到指定终点的带权最短路径

核心步骤

        1)确定起点,终点

        2)从未走过的点中选取从起点到权值最小点作为中心点

        3)如果满足 起点到中心点权值 + 中心点到指定其他点的权值 < 起点到其他点的权值,

        即Weight[start] [center] +Weight [center] [other] < Weight [start] [center] ,

        简言之,有更短的路径就取更短的路

理论模拟

        以A为起点,D为终点,如图所示 径, 更新记录更短权值路径

最短路径:迪杰斯特拉算法_第1张图片

 从未走过的点中选取权值最小点,即A作为中心点,标记A走过,更新起点到B、F、G的路径

 最短路径:迪杰斯特拉算法_第2张图片

从未走过的点中选取权值最小点,即B, 并且W:B->C + W:A->C = 12 + 10 < +oo ,更新起点A到C的路径和,

即W: A-> C =W: A-> B -> C =12+10 =22

 最短路径:迪杰斯特拉算法_第3张图片

 继续从未走过的点中选取权值最小点G, W: A -> E =+oo > W: A->G ->E =14+8 =22 ,

 更新W: A->E 为22

最短路径:迪杰斯特拉算法_第4张图片

选取F, 由于W:A->F->E=16+2 =18 <22 更新 W: A-> E =18 ,

最短路径:迪杰斯特拉算法_第5张图片

 选取E,由于W:A->E->D=18+4=22<+oo,则更新W: A->D =22

最短路径:迪杰斯特拉算法_第6张图片

 选取C,无可更新点

最短路径:迪杰斯特拉算法_第7张图片

 到达终点D! 最短路径为A->F->E->D ,最短路径和为22

最短路径:迪杰斯特拉算法_第8张图片

 

Java代码实现
 顶点
//顶点类
public class Vertex {
    public String Number;  //顶点编号
    public ListneighborVertexs;    //邻居顶点
    public Mapweights;     //与邻居节点之间的权值

    public Vertex(String number) {
        this.Number = number;
        this.neighborVertexs=new LinkedList<>();
        this.weights=new HashMap<>();
    }
}
public class Edge {
    public Vertex start;
    public Vertex end;
    public Integer weight;

    public Edge(Vertex start, Vertex end, Integer weight) {
        this.start = start;
        this.end = end;
        this.weight = weight;
    }
}
最短路径返回结果
public class MinPathResult {
    public String minPathString;    //将最短路径拼接成字符串形式,如 A->B->C
    public ListminPathList; //将起点到终点的路径储存在List集合中
    public Integer minPathSum;  //记录起点到终点的最短路径和
    public MinPathResult(List minPathList, String minPathString,Integer minPathSum) {
        this.minPathString = minPathString;
        this.minPathList = minPathList;
        this.minPathSum=minPathSum;
    }

    @Override
    public String toString() {
        return "Result{" +
                "minPathString:'" + minPathString +"  minPathSum:"+minPathSum+
                '}';
    }
}
Dijkstra算法的实现,适用于无向图
import java.util.*;
//适用于无向图
public class DijkstraOperator {
    private Listvertexs;    //全部顶点
    private Listedges;        //所有边
    private Mapvertexs_map;  //通过顶点编号找到顶点

    private final static Integer INF=Integer.MAX_VALUE;     //代表无穷大

    public DijkstraOperator(List vertexs, List edges) {
        this.vertexs = vertexs;
        this.edges = edges;
        this.vertexs_map=new HashMap<>();
        //构建编号映射顶点
        for(Vertex v:vertexs)
        {
            vertexs_map.put(v.Number,v);
        }

        //填充所有顶点的邻居以及权值
        for(int i=0;ivisited=new HashMap<>();
        //用哈希表记录顶点的前驱
        MappreVertex=new HashMap<>();
        //利用哈希表记录起点到任意一点的最短路径
        MapminPath=new HashMap<>();

        //初始化三个表
        for(int i=0;itargetPath=new LinkedList<>();

        for(Vertex curVer=endVertex;curVer!=startVertex;curVer=preVertex.get(curVer))
        {
            targetPath.addFirst(curVer);
        }
        targetPath.addFirst(startVertex);

        //拼接最短路径
        StringBuffer minPathStringBuffer=new StringBuffer();
        Integer pathSum=0;
        for(int i=0;i< targetPath.size();i++)
        {
            minPathStringBuffer.append(targetPath.get(i).Number);
            if(i!= targetPath.size()-1)
            {
                pathSum=pathSum+targetPath.get(i).weights.get(targetPath.get(i+1));
                minPathStringBuffer.append("->");
            }
        }
        return new MinPathResult(targetPath, minPathStringBuffer.toString(),pathSum);
    }
}
测试函数
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner scanner=new Scanner(System.in);

        Listvertexs=new LinkedList<>();
        Listedges=new LinkedList<>();

        System.out.println("请输入顶点的数量:");
        Integer vexcnt= scanner.nextInt();
        System.out.println("请输入这些顶点编号:");
        for(int i=0;iminPathResults=new ArrayList<>();

        for(int i=0;i< vertexs.size();i++)
        {
            for(int j=i+1;j< vertexs.size();j++)
            {
                minPathResults.add(dijkstra.getMinPath(vertexs.get(i).Number,vertexs.get(j).Number));
                System.out.println(minPathResults.get(minPathResults.size()-1));
            }
        }

    }
}
测试输入与输出结果
//输入部分
请输入顶点的数量:
7
请输入这些顶点编号:
A B C D E F G
请输入边的数量:
12
请输入这些边的端点编号和权值:
A B 12
A F 16
A G 14
B C 10
B F 7
G F 9
G E 8
F C 6
F E 2
C D 3
C E 5
E D 4

//输出部分
Result{minPathString:'A->B  minPathSum:12}
Result{minPathString:'A->B->C  minPathSum:22}
Result{minPathString:'A->F->E->D  minPathSum:22}
Result{minPathString:'A->F->E  minPathSum:18}
Result{minPathString:'A->F  minPathSum:16}
Result{minPathString:'A->G  minPathSum:14}
Result{minPathString:'B->C  minPathSum:10}
Result{minPathString:'B->F->E->D  minPathSum:13}
Result{minPathString:'B->F->E  minPathSum:9}
Result{minPathString:'B->F  minPathSum:7}
Result{minPathString:'B->F->G  minPathSum:16}
Result{minPathString:'C->D  minPathSum:3}
Result{minPathString:'C->E  minPathSum:5}
Result{minPathString:'C->F  minPathSum:6}
Result{minPathString:'C->E->G  minPathSum:13}
Result{minPathString:'D->E  minPathSum:4}
Result{minPathString:'D->E->F  minPathSum:6}
Result{minPathString:'D->E->G  minPathSum:12}
Result{minPathString:'E->F  minPathSum:2}
Result{minPathString:'E->G  minPathSum:8}
Result{minPathString:'F->G  minPathSum:9}

进程已结束,退出代码为 0

你可能感兴趣的:(数据结构与算法,算法,数据结构)