Dijkstra算法实现(JAVA)

本文深入讲解了Dijkstra算法,一种解决有权图中最短路径问题的经典算法。文章详细介绍了算法的提出背景、核心思想及其实现过程,并通过一个具体示例展示了算法的实际应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

DIjkstra算法介绍
迪杰斯特拉算法(Dijkstra)是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法。是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路径问题。迪杰斯特拉算法主要特点是从起始点开始,采用贪心算法的策略,每次遍历到始点距离最近且未访问过的顶点的邻接节点,直到扩展到终点为止。
DIjkstra算法思想
算法开始选择一个顶点s作为开始节点。d表示各个节点距s的距离,p表示路径。Dijkstra算法按阶段进行,正像无权最短路径算法一样。在每个阶段,Dijkstra选择一个顶点v,他在所有的unknown的顶点中具有最小的dv,同时算法声明从s到v的最短路径known。其余阶段则更新由v已知而造成的距离变化。
下面通过一个例子说明
首先给出一张赋权图
在这里插入图片描述

我们将A作为开始节点S。实现代码如下:

import java.util.ArrayList;
import java.util.Arrays;


public class Graph {
    public static void main(String[] args) {
        project01.Graph graph = new project01.Graph(5);
        graph.addVertax("A");
        graph.addVertax("B");
        graph.addVertax("C");
        graph.addVertax("D");
        graph.addVertax("E");


        graph.addEdges(0,1,10);
        graph.addEdges(0,2,2);
        graph.addEdges(2,1,1);
        graph.addEdges(2,4,7);
        graph.addEdges(1,4,1);
        graph.addEdges(4,3,3);

        showEdges();
        graph.dijkStra(0);



    }
    //这里是定点数n,顶点集合Vertax,边的集合edges,是否被访问过得标记符isvisited
    private int n;
    private int numberOfEdges;
    private double[] distance;
    private String[] path;
    private ArrayList<String> Vertax;
    private static int[][] edges;
    private boolean[] isVisited;
    public  Graph(int n){
        this.n = n;
        numberOfEdges=0;
        Vertax = new ArrayList<>(n);
        edges  = new int[n][n];
        isVisited = new boolean[n+1];
        distance = new double[n];
        for (int i = 0; i <n ; i++) {
            distance[i] = Double.POSITIVE_INFINITY;
        }

        path = new String[n];
        for (int i = 0; i <n ; i++) {
            path[i] = "";
        }
    }

    //打印邻接表
    public static void showEdges(){
        for (int[] edse: edges
        ) {
            System.out.println(Arrays.toString(edse));
        }

    }
    //获取顶点数
    public  int GetSizeOfGraph(ArrayList<String> Vertax){
        return Vertax.size();
    }
    //添加顶点
    public  void addVertax(String s){
        Vertax.add(s);
    }
    //获取指定顶点的第一个相邻顶点
    public int getFirstCO(int index){
        for (int i = 0; i <Vertax.size() ; i++) {
            if (edges[index][i]>0) return i;
        }
        return n;
    }
    //获取指定顶点的顺次相邻顶点
    public int getNextCO(int index,int firstCO){
        for (int i =firstCO+1 ; i <Vertax.size() ; i++) {
            if (edges[index][i]>0) return i;
        }
        return n;
    }
    //添加边
    public  void addEdges(int e1,int e2 , int weight){
        edges[e1][e2] = weight;
        //edges[e2][e1] = weight;
        numberOfEdges++;
    }
    //获取边数
    public int getNumberOfEdges(){
        return numberOfEdges;
    }

    public void dijkStra(int index ){

        //CO 是迭代所需坐标,headIndex为每次DIJKSTRA的启动顶点


        int CO;
        int headIndex = index;
        //
        //为初始点设置距初始点距离,自然为0
        distance[index]=0;


        //之后为每个顶点做如下操作
        //1.设置本顶点为known,本点的距离和路径不用管,因为之前已经设计好
        //2.寻找本顶点的每个相邻顶点。对于unknown的顶点,比较沿本顶点到达的距离和其原本距离,若小于原本距离,则更新距离,更新路径
        //3.本顶点设置结束后,通过indexGet函数,找出当前unknown顶点中距离最小的顶点,将其作为下一个顶点执行步骤2

        while (!isVisited[headIndex]){

            //CO为第一个没被visited的CO
            CO = getFirstCO(headIndex);
            while(isVisited[CO]){
                CO = getNextCO(headIndex,CO);
            }

            //如果headIndex顶点没有未被访问过的相邻顶点,则获得顶点坐标为n,说明他是最后一个unknown节点,仅仅需要设置为known即可
            if (CO==n) {
                isVisited[headIndex]=true;
                //System.out.println("没找到坐标");
            }
            //通过循环将所有相邻顶点执行步骤2
            else {
                while (!isVisited[CO]&&CO<n) {
                    isVisited[headIndex]=true;
                    double currentDis = distance[headIndex]+edges[headIndex][CO];
                    if (currentDis<distance[CO]) {
                        distance[CO] = currentDis;

                        path[CO] = path[headIndex]+" "+Vertax.get(headIndex);
                    }

                    CO = getNextCO(headIndex, CO);

                }
            }

            headIndex = indexGet(distance,isVisited);


        }
        for (int i = 0; i <n ; i++) {
            path[i] = path[i]+" "+Vertax.get(i);
        }
        System.out.println("开始节点: "+Vertax.get(index));
        for (int i = 0; i <n ; i++) {
            System.out.println(Vertax.get(i)+"   "+distance[i]+"   "+path[i]);
        }


    }
    //通过给定距离矩阵和访问矩阵,返回下一个需要的顶点
    public int indexGet(double[] distance, boolean[] isVisited){
        int j=0;
        double mindis=Double.POSITIVE_INFINITY;
        for (int i = 0; i < distance.length; i++) {
            if (!isVisited[i]){
                if(distance[i]<mindis){
                    mindis=distance[i];
                    j=i;
                }
            }
        }
        return j;
    }
}

最终结果如下:
邻接矩阵图
顶点、距离、路径

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值