Dijkstra

Dijkstra算法

介绍

Dijkstra算法,是用于求解图(这里介绍有向图)的最短路径算法。采用贪婪原则,逐步求解起点到图其他点的最短路径。

算法描述

从起点出发,寻找距离最近的点,找到距离最近的点,再尝试将最近的点作为中间点,来计算到其他点的距离,看是否相对之前有所减少,减少就记录下这个距离,再次寻找剩余点中距离最近的点,知道所有点都被选中。

这么描述可能很抽象,结合例子来看:

在这里插入图片描述

图在数据结构中,有多种表现方式,这里采用邻接矩阵记录

在这里插入图片描述

到自身距离为0,没有直接相连记为无穷

需要三个数组:

dist[j]:表示起点到j点的最短距离

path[j]=i:表示到达j点前经过的最后一个点为i

set[i](布尔):表示是否求得起点到i的距离

(1)初始化

假设0为起点,图转化的临界矩阵为M,需要做以下初始化

  • set[0]=true,标记0已经求得,set[i]=false(i!=0),标记其他点未读
  • dist[i]=M0i,将0到其他点的距离作为最短路径
  • path[i]=-1,-1表示没有起点,path[i]=j表示0->…->j->i,因此,如果M0j不是无穷,则表示最短路径经0点,令path[j]=0,否则path[j]=-1
(2)迭代求解

每一次计算都会得到起点到一个点的最短距离,所以只需要n-1(n为顶点个数)就可以求出到所有点的最短路径,一下过程需要重复执行n-1次:

  1. 根据dist[]数据找到值最小的点j,dist[j]就是起点到j的最短距离
  2. set[j]=true,标记起点到j的最短距离已找到
  3. path[j]=preNode,记录起点到达j的最短路径上,经过preNode才到达j,即preNode是起点到达j的最短路径上的倒数第二个节点
  4. 更新dist[],尝试将j作为中间点,来减少起点到达剩余点的距离,如果dist[k]>dist[j]+Mjk(其中set[k]==false),则令dist[k]=dist[j]+Mjk,且令path[k]=j,记录下最短路径上的倒数第二点
(3)结果

按照上述步骤,得到计算结果:

path: [ -1, 4, 1, 4, 0 ]

dist: [ 0, 8, 9, 7, 5 ]

解析:

目的节点最短路径距离
00->00
10->4->18
20->4->3->1->29
30->4->37
40->45
TypeScript实现

模块化./modules/Dijkstra.ts

const Dijkstra = (startNode:number,map:number[][]):any=>{
    let dist:number[]=[]
    let path:number[]=[]
    let set:boolean[]=[]
    // 初始化
    for(let i=0;i<map[0].length;i++){
       if(startNode!==i){
            dist[i]=map[startNode][i]
            set[i]=false
            if(map[startNode][i]!=Number.MAX_VALUE){
                path[i]=startNode
            }
       }else{
            dist[i]=0
            set[i]=true
            path[i]=-1
       }
       
    }

    
    let preNode:number=startNode
    for(let i=1;i<map.length;i++){
        const {min,minIndex}=getMinAndIndex(dist,set)
        if(minIndex==-1)return false;
        set[minIndex]=true
        // 更新dist
        for(let j=0;j<map.length;j++){
            if(set[j]!==true&&dist[j]>dist[minIndex]+map[minIndex][j]){
                dist[j]=dist[minIndex]+map[minIndex][j]
                // 选出到达目的距离最短的点
                path[j]=minIndex
            }
        }
        //console.log(min,minIndex);

    }
    return {
        path,dist
    }
}

const getMinAndIndex=(arr:number[],set:boolean[]):any=>{
    let min:number=Number.MAX_VALUE
    let minIndex:number=-1

    for(let i=1;i<arr.length;i++){
        if(set[i]===false && min>arr[i]){
            min=arr[i]
            minIndex=i
        }
    }
    
    return {
        min,minIndex
    }
}

export {getMinAndIndex,Dijkstra}

测试

import {getMinAndIndex,Dijkstra} from './modules/Dijkstra'

let inf:number=Number.MAX_VALUE
let arr:number[][]=
                [
                    [0,10,inf,inf,5],
                    [inf,0,1,inf,2],
                    [inf,inf,0,4,inf],
                    [inf,inf,6,0,inf],
                    [inf,3,9,2,inf]
                ]
let res = Dijkstra(0,arr)
console.log(res)

结果:

在这里插入图片描述

总结

Dijkstra算法,用于解决图的最短路径问题,一起点为中心,逐步向四周扩散,通过不断的更新路径,来尝试获得最短路径,采用贪婪的思想,获得触发点到其余点的最短路径及最短距离,Dijkstra算法具有广泛的应用。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值