算法--基础--11--迪杰斯特拉(Dijkstra)

算法–基础–11–迪杰斯特拉(Dijkstra)


1、定义

  • 最短路径算法,用于计算一个节点到其他节点的最短路径。
  • 特点:是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止。

2、算法思路

  1. 初始时,S只包含起点s;U包含除s外的其他顶点,且U中顶点的距离为"起点s到该顶点的距离"[例如,U中顶点v的距离为(s,v)的长度,然后s和v不相邻,则v的距离为∞]。
  2. 从U中选出"距离最短的顶点k",并将顶点k加入到S中;同时,从U中移除顶点k。
  3. 更新U中各个顶点到起点s的距离。之所以更新U中顶点的距离,是由于上一步中确定了k是求出最短路径的顶点,从而可以利用k来更新其它顶点的距离;例如,(s,v)的距离可能大于(s,k)+(k,v)的距离。
  4. 重复步骤2和3,直到遍历完所有顶点。

3、算法图解

选定A节点并初始化

这里写图片描述

执行上述2,3步骤,找出U集合中路径最短的节点D 加入S集合,从U中移除节点D,更新U中各个顶点到起点A的距离,根据(AD距离 + D到B,C,E的距离< A到B,C,E 的距离)来更新U集合

这里写图片描述

这时候 B, C 都为3,没关系。其实这时候他俩都是最短距离,如果从算法逻辑来讲的话,会先取到B点。 执行步骤2,3

这里写图片描述

思路就是这样,往后就是大同小异

这里写图片描述
这里写图片描述

4、代码实现

package Test;

import java.util.ArrayList;
import java.util.List;

public class Dijkstra {
    public static final int M = 10000; // 代表正无穷
    
    public static void main(String[] args) {
        // 二维数组每一行分别是 A、B、C、D、E 各点到其余点的距离, 
        // A -> A 距离为0, 常量M 为正无穷
        int[][] weight1 = {{0,4,M,2,M}, //A节点到A、B、C、D、E 各点到其余点的距离
                {4,0,4,1,M}, //B节点到A、B、C、D、E 各点到其余点的距离
                {M,4,0,1,3}, //C节点到A、B、C、D、E 各点到其余点的距离
                {2,1,1,0,7}, //D节点到A、B、C、D、E 各点到其余点的距离  
                {M,M,3,7,0}  //E节点到A、B、C、D、E 各点到其余点的距离
            };
        
        //测试A节点到其他节点的距离
        int start = 0;
        dijkstra(weight1, start);
           
    }
    /**
     * 
     * 描述:将数字转换为对应的节点(A,B,C,D,E)
     * @param 
     * @return
     */
    public static  String getNode(int i) {
    	String node=null;
    	switch (i) {
		case 0:
			node="A";
			break;
		case 1:
			node="B";
			break;
		case 2:
			node="C";
			break;
		case 3:
			node="D";
			break;
		case 4:
			node="E";
			break;
		default:
			break;
		}
		return node;
    }
    public static void dijkstra(int[][] weight, int start) {
        // 接受一个有向图的权重矩阵,和一个起点编号start(从0编号,顶点存在数组中)
        // 返回一个int[] 数组shortPath,表示从start到它的最短路径长度
        int n = weight.length; // 顶点(0,1,2,3,4)
        //S的作用是记录已求出最短路径的顶点集合
        int[] s = new int[n];  
        
        //U则是记录还未求出最短路径的顶点集合
        List<Integer> u= new ArrayList<Integer>(); 
			for (int i=0;i<n;i++) {
				u.add(i);
		}
			
     // 保存start到其他各点最短路径的字符串表示
        String[] path = new String[n]; 
        for (int i = 0; i < n; i++){
        	   path[i] = new String(getNode(start) + "-->" + getNode(i));//默认设置起点到各个顶点的输出格式
        }
         
       
			
		// 初始化,第一个顶点已经求出
        s[start] = 0;
        //U中排除第一个顶点
        u.remove(Integer.valueOf(start));

        for (int count = 1; count < n; count++) { // 要加入n-1个顶点
            int k = -1; // 选出一个距离初始顶点start最近的未标记顶点
            int dmin = Integer.MAX_VALUE;
            //选择集合中未标记过的最短路径的节点(相当于在U中获取最小路径的节点)
            for (int i = 0; i < n; i++) {
                if (u.contains(i) && weight[start][i] < dmin) {
                    dmin = weight[start][i];
                    k = i;
                }
            }
            // 将选出的最短路径节点放到集合S中,并设置该节点的路径大小
            s[k] = dmin;
            u.remove(Integer.valueOf(k));//排除以放到S集合的节点

            // 以k为中间点,修正从start到未访问各点的距离
            for (int i = 0; i < n; i++) {//和所有没有标记最短路径进行对比,更新U中的所有最短距离
                //如果 '起始点到当前点距离' + '当前点到某点距离' < '起始点到某点距离', 则更新
                if (u.contains(i)  && weight[start][k] + weight[k][i] < weight[start][i]) {
                    weight[start][i] = weight[start][k] + weight[k][i];//修正起始节点到某点的最短距离
                    path[i] = path[k] + "-->" + getNode(i);//
                }
            }
        }
        //输出
        for (int i = 0; i < n; i++) {
            System.out.println("从" + getNode(start) + "出发到" + getNode(i) + "最短距离为:"+s[i]+",最短路径为:" + path[i]);
        }
    }
    
}

 


结果
从A出发到A最短距离为:0,最短路径为:A-->A
从A出发到B最短距离为:3,最短路径为:A-->D-->B
从A出发到C最短距离为:3,最短路径为:A-->D-->C
从A出发到D最短距离为:2,最短路径为:A-->D
从A出发到E最短距离为:6,最短路径为:A-->D-->C-->E

​​​​​​​

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值