【算法学习】带权有向图的最短路径问题——Dijkstra算法

【算法学习】带权有向图的最短路径问题——Dijkstra算法

实现过程参考视频内容:实现过程点我查看!

个人感觉这是我看过的教程中较容易理解的一个视频,我的算法也是根据这个写的,具体实现过程看视频!!

 

Dijkstra算法的核心就是松弛技术

具体实现代码,其中出现的MyQueue和MyStack是我自己实现的数据结构,ctrl+F换成自己的或者自带的即可

package IOTest.graph;

import IOTest.queue.MyQueue;
import IOTest.stack.MyStack;

@SuppressWarnings("all")
public class MyDijkstraShortestPath {
    public static void main(String[] args) {
        MyEdgeWeightedDigraph gragh = new MyEdgeWeightedDigraph(6);
        gragh.addEdge(new MyDirectedEdge(0,1,2));
        gragh.addEdge(new MyDirectedEdge(1,2,1));
        gragh.addEdge(new MyDirectedEdge(0,2,4));
        gragh.addEdge(new MyDirectedEdge(2,3,4));
        gragh.addEdge(new MyDirectedEdge(2,4,5));
        gragh.addEdge(new MyDirectedEdge(4,5,3));
        gragh.addEdge(new MyDirectedEdge(3,5,3));
        gragh.addEdge(new MyDirectedEdge(1,3,6));
        MyDijkstraShortestPath myDijkstraShortestPath = new MyDijkstraShortestPath(gragh,0);
        MyStack theShortestPath = myDijkstraShortestPath.getTheShortestPath(5);
        theShortestPath.forEach(item ->{
            System.out.print(item+"===>");
        });
    }

    /**
     * 从起点到某个结点的最短路径
     */
    private MyStack<Integer> theShortestPath;

    /**
     * 记录某点的前一个点
     */
    private int[] frontPoint;

    /**
     * 其余各点到起点的距离
     */
    private double[] distance;

    /**
     * 记录某个顶点是否被标记为了最优结点
     */
    private boolean[] certain;

    /**
     * 待处理的图
     */
    private MyEdgeWeightedDigraph graph;

    public MyDijkstraShortestPath(MyEdgeWeightedDigraph graph,int start) {
        int V = graph.getV();
        this.distance = new double[V];
        this.certain = new boolean[V];
        this.frontPoint = new int[V];
        this.theShortestPath = new MyStack<>();
        this.graph = graph;

        for (int i = 0; i < distance.length; i++) {
            distance[i] = Double.MAX_VALUE;
        }
        distance[start] = 0.0;
        frontPoint[start] = start;

        visit(start);
    }

    private void visit(int v) {
        int min = findMin();
        if(min == distance.length){return;}
        certain[min] = true;
        MyQueue<MyDirectedEdge> allNearEdges = graph.getAllNearEdges(min);
        for (MyDirectedEdge allNearEdge : allNearEdges) {
            int start = allNearEdge.getStart();
            int end = allNearEdge.getEnd();
            double weight = allNearEdge.getWeight();
            // 比较从起点经过当前顶点到达目标结点的距离与直接动起点到目标结点的距离
            // 如果中转的距离比直接到的距离小,则更新距离表,并把目标结点的前一个结点设置为当前结点
            if(distance[start]+weight<distance[end]){
                distance[end] = distance[start]+weight;
                frontPoint[end] = v;
            }
        }

        for (double v1 : distance) {
            System.out.println(v1+" ");
        }
        System.out.println("______开始下一轮搜索");
        visit(findMin());
    }

    private int findMin() {
        // 只在未被标为最短路径最优结点的剩下的结点中寻找
        int minIndex = 0;
        for (int i = 0; i < distance.length; i++) {
            if(certain[i]==true){
                minIndex++;
                continue;
            }else if(distance[i]<=distance[minIndex]){
                minIndex = i;
            }
        }
        return minIndex;
    }

    public MyStack getTheShortestPath(int aimPoint) {
        path(aimPoint);
        return theShortestPath;
    }

    private void path(int aimPoint) {
        int pre =  frontPoint[aimPoint];
        theShortestPath.push(aimPoint);
        if(pre == aimPoint){return ;}
        getTheShortestPath(pre);
    }
}

 

posted @ 2022-03-15 17:14  把你画在马桶上  阅读(212)  评论(0)    收藏  举报