Java实现之迪杰斯特拉(Dijkstra)算法

一.问题引入

1.问题引入

1)战争时期,胜利乡有7个村庄(A,B,C,D,E,F,G),现在有六个邮差,从G点出发,需要分别
把邮件分别送到A, B,C,D,E,F六个村庄

2)各个村庄的距离用边线表示(权),比如A-B距离5公里

3)问:如何计算出G村庄到其它各个村庄的最短距离?

4)如果从其它点出发到各个点的最短距离又是多少?

二.迪杰斯特拉(Dijkstra)算法

1.基本介绍

迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个结点到其他结点的最短路径。它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止。

2.算法过程

迪杰斯特拉(Dijkstra)算法主要步骤

  1. 变量g表示邻接矩阵存储的带权图G,S ={v0},将v0到其余顶点的路径长度初始化为权值,即dis[i] = matrix[v0][i]
  2. 找出当前最短距离dis[k] = Min(dis[i] | vi ∈V - S),则vk为当前求出的下一条从vo出发的最短路径的终点,将vk纳入S,并从V一S中删除
  3. 更新从v0出发到集合V - S中顶点v;的最短路径的长度:如果在S中存在vk;使得dis[k] +matrix[k][i]<dist[i](新间接距离<直接距离/当前间接距离),则将dis[i]修改为新间接距离
  4. 重复②、③步骤n-1次,即可按最短路径长度的递增顺序,逐个求出v,到图中其它每个顶点的最短路径

3.代码实现

public class Dijkstra {
    public static final int N = 65535;

    public static void main(String[] args) {
        char[] vertex = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
        //邻接矩阵
        int[][] matrix = new int[vertex.length][vertex.length];
        matrix[0] = new int[]{N, 5, 7, N, N, N, 2};
        matrix[1] = new int[]{5, N, N, 9, N, N, 3};
        matrix[2] = new int[]{7, N, N, N, 8, N, N};
        matrix[3] = new int[]{N, 9, N, N, N, 4, N};
        matrix[4] = new int[]{N, N, 8, N, N, 5, 4};
        matrix[5] = new int[]{N, N, N, 4, 5, N, 6};
        matrix[6] = new int[]{2, 3, N, N, 4, 6, N};
        //创建Graph对象
        Graph graph = new Graph(vertex, matrix);
        graph.showGraph();
        graph.dijkstra(6);


    }
}

class Graph {
    char[] vertex;  //保存结点的数据
    int[][] matrix; //存放边,就是邻接矩阵
    VisitedVertex visitedVertex; //已经访问的顶点的集合

    public Graph(char[] vertex, int[][] matrix) {
        this.vertex = vertex;
        this.matrix = matrix;
    }

    //显示邻接矩阵
    public void showGraph() {
        for (int i = 0; i < vertex.length; i++) {
            for (int j = 1; j < vertex.length; j++) {
                System.out.printf("%-8d", matrix[i][j]);
            }
            System.out.println();
        }
    }

    //迪杰斯特拉算法
    //index 表示出发顶点对应的下标
    public void dijkstra(int index) {
        visitedVertex = new VisitedVertex(vertex.length, index);
        update(index);
        for(int i=0;i<vertex.length;i++){
            index= visitedVertex.getNextIndex(); //访问并返回新的访问节点
            update(index);
        }
        visitedVertex.show();



    }

    //更新index下标顶点到周围顶点的前驱顶点,
    public void update(int index) {
        //根据遍历邻接矩阵的matrix[index]行
        int len;
        for (int i = 0; i < matrix[index].length; i++) {
            if(matrix[index][i]==Dijkstra.N)
                continue;
            len = visitedVertex.getDistance(index) + matrix[index][i];
            if (!visitedVertex.isVisted(i) && len < visitedVertex.getDistance(i)) {
                visitedVertex.updateDistance(i, len);  //更新出发顶点到i顶点的距离
                visitedVertex.updatePre(i, index);     //更新i顶点的前驱为index

            }
        }
    }
}

//已访问项点集合
class VisitedVertex {
    //记录各个顶点是否访问过 true表示访问过, false未访问,会动态更新
    public boolean[] isVisted;
    //每个下标对应的值为前一个顶点下标,会动态更新
    public int[] pre_visited;
    //记录出发顶点到其他所有顶点的距离,比如G为出发顶点,就会记录G到其它顶点的距离,会动态更新,求的最短距离就会存放到dis
    public int[] distance;

    //构造器

    /**
     * @param length 顶点的个数
     * @param index  出发顶点对应的下标
     */
    public VisitedVertex(int length, int index) {
        this.isVisted = new boolean[length];
        this.pre_visited = new int[length];
        this.distance = new int[length];
        this.isVisted[index] = true;
        //初始化dis数组
        Arrays.fill(distance, Dijkstra.N);
        this.distance[index] = 0;   //出发顶点的访问距离为0

    }

    //判断下标为index顶点是否访问过
    public boolean isVisted(int index) {
        return isVisted[index];
    }

    //更新出发顶点到index顶点的距离
    public void updateDistance(int index, int length) {
        distance[index] = length;

    }
    //更新pre这个顶点为index的前驱顶点

    /**
     * @param pre   当前节点的前驱节点
     * @param index 当前结点
     */
    public void updatePre(int index, int pre) {
        pre_visited[index] = pre;

    }

    //返回出发顶点到index顶点的距离
    public int getDistance(int index) {
        return distance[index];
    }

    //继续选择并选择新的访问顶点
    public int getNextIndex() {
        int min = Dijkstra.N, index = 0;
        for (int i = 0; i < isVisted.length; i++) {
            if (!isVisted[i] && distance[i] < min) {
                min = distance[i];
                index = i;

            }


        }
        //更新index为已经访问过的
        isVisted[index] = true;
        return index;

    }
    public void show(){
        //输出isVisited数组
        System.out.println(Arrays.toString(isVisted));
        //输出pre_visited数组
        System.out.println(Arrays.toString(pre_visited));
        //输出distance数组
        System.out.println(Arrays.toString(distance));
    }
}

打印结果:

[true, true, true, true, true, true, true]
[6, 6, 0, 5, 6, 6, 0]
[2, 3, 9, 10, 4, 6, 0]

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 的方法有很多种。其中一种是使用邻接矩阵来存储图中的边,然后通过循环更新每个结点的最短路径。代码实现如下: ``` import java.util.*; public class Dijkstra { static final int V=9; int minDistance(int dist[], Boolean sptSet[]) { int min = Integer.MAX_VALUE, min_index=-1; for (int v = 0; v < V; v++) if (sptSet[v] == false && dist[v] <= min) { min = dist[v]; min_index = v; } return min_index; } void printSolution(int dist[], int n) { System.out.println("Vertex Distance from Source"); for (int i = 0; i < V; i++) System.out.println(i+" tt "+dist[i]); } void dijkstra(int graph[][], int src) { int dist[] = new int[V]; Boolean sptSet[] = new Boolean[V]; for (int i = 0; i < V; i++) { dist[i] = Integer.MAX_VALUE; sptSet[i] = false; } dist[src] = 0; for (int count = 0; count < V-1; count++) { int u = minDistance(dist, sptSet); sptSet[u] = true; for (int v = 0; v < V; v++) if (!sptSet[v] && graph[u][v]!=0 && dist[u]+graph[u][v] < dist[v]) dist[v] = dist[u] + graph[u][v]; } printSolution(dist, V); } public static void main (String[] args) { int graph[][] = new int[][]{{0, 4, 0, 0, 0, 0, 0, 8, 0}, {4, 0, 8, 0, 0, 0, 0, 11, 0}, {0, 8, 0, 7, 0, 4, 0, 0, 2}, {0, 0, 7, 0, 9, 14, 0, 0, 0}, {0, 0, 0, 9, 0, 10, 0, 0, 0}, {0, 0, 4, 14, 10, 0, 2, 0, 0}, {0, 0, 0, 0, 0, 2, 0, 1, 6}, {8, 11, 0, 0, 0, 0, 1, 0, 7}, {0, 0, 2, 0, 0, 0, 6, 7, 0} }; Dijkstra t = new Dijkstra(); t.dijkstra(graph, 0); } } ``` ### 回答2: 迪杰斯特拉算法是一种用于在加权图中寻找最短路径的算法。使用Java语言实现迪杰斯特拉算法的步骤如下: 1. 创建一个Graph类来表示加权图。图可以使用邻接矩阵或邻接表来表示。 2. 创建一个Edge类来表示图中的边。边包含一个起始顶点、终止顶点和权重。 3. 创建一个Vertex类来表示图中的顶点。顶点包含一个标识符和一个最小权重。 4. 创建一个Dijkstra类来实现迪杰斯特拉算法。 5. 在Dijkstra类中添加一个方法来计算最短路径。这个方法接受一个起始顶点作为参数。 6. 在Dijkstra类中,创建一个集合来存储已访问的顶点。初始化集合,将起始顶点加入集合。 7. 创建一个优先队列来存储未访问的顶点。将起始顶点的最小权重设置为0并加入队列。 8. 创建一个循环,直到优先队列为空。在每次循环中,从队列中取出权重最小的顶点。 9. 对于取出的顶点,遍历其邻接顶点。如果邻接顶点未被访问过,计算其新的最小权重。如果新的最小权重小于原来的最小权重,更新邻接顶点的最小权重并将其加入队列。 10. 循环结束后,可以通过遍历每个顶点的最小权重来找到最短路径。 以上就是使用Java语言实现迪杰斯特拉算法的基本步骤。通过遵循这些步骤,我们可以编写出一个能够找到加权图中最短路径的Dijkstra类。 ### 回答3: 迪杰斯特拉Dijkstra算法是一种解决单源最短路径问题的经典算法。使用Java语言实现迪杰斯特拉算法的步骤如下: 1. 首先,创建一个有向图(Graph)类。该类中包括构造函数和两个方法:addEdge()方法用于添加边,和findShortestPath()方法用于查找最短路径。 2. 在构造函数中,初始化图的顶点数量和邻接矩阵。首先,创建一个二维数组来表示邻接矩阵,初始化值为无穷大。然后,创建一个ArrayList来存储顶点集合。 3. 利用addEdge()方法添加边。这个方法将两个顶点之间的距离存储在邻接矩阵中。 4. 实现findShortestPath()方法。该方法接收两个参数:起始顶点和目标顶点。首先,创建一个一维数组distances,用于存储起始顶点到其他顶点的最短距离。将起始顶点到自身的距离设置为0,其他顶点的距离设置为无穷大。同时,创建一个数组visited,用于记录顶点的访问状态。 5. 在一个循环中,遍历所有顶点,并更新距离数组的值。首先,在未访问的顶点中选择最小距离的顶点,并将其标记为已访问。然后,遍历所有顶点,如果当前顶点未被访问且通过最小距离的顶点可到达当前顶点,则更新最短距离。 6. 最后,打印最短路径。根据最短路径的整理顺序,从目标顶点开始向前查找,直到到达起始顶点。将路径上的顶点依次保存到一个栈中,然后依次出栈打印即可。 以上就是使用Java语言实现迪杰斯特拉算法的大致步骤。通过构建有向图和利用距离数组不断更新最短路径,可以在时间复杂度为O(V^2)的情况下解决单源最短路径问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

允歆辰丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值