在网图中,最短路径的概论:

两顶点之间经过的边上权值之和最少的路径,并且我们称路径上的第一个顶点是源点,最后一个顶点是终点。

维基百科上面的解释:

这个算法是通过为每个顶点 v 保留目前为止所找到的从s到v的最短路径来工作的。

初始时,原点 s 的路径长度值被赋为 0 (d[s] = 0),若存在能直接到达的边(s,m),则把d[m]设为w(s,m),同时把所有其他(s不能直接到达的)顶点的路径长度设为无穷大,即表示我们不知道任何通向这些顶点的路径(对于 V 中所有顶点 v除 s 和上述 m 外 d[v] = ∞)。

当算法退出时,d[v] 中存储的便是从 s 到 v 的最短路径,或者如果路径不存在的话是无穷大。

Dijkstra 算法的基础操作是边的拓展:如果存在一条从 u 到 v 的边,那么从 s 到 v 的最短路径可以通过将边(uv)添加到尾部来拓展一条从 s 到 u 的路径。

这条路径的长度是 d[u] + w(u, v)。如果这个值比目前已知的 d[v] 的值要小,我们可以用新值来替代当前 d[v] 中的值。

拓展边的操作一直运行到所有的 d[v] 都代表从 s 到 v 最短路径的花费。

这个算法经过组织因而当 d[u] 达到它最终的值的时候每条边(uv)都只被拓展一次。

算法维护两个顶点集 S 和 Q。集合 S 保留了我们已知的所有 d[v] 的值已经是最短路径的值顶点,而集合 Q 则保留其他所有顶点。

集合S初始状态为空,而后每一步都有一个顶点从 Q 移动到 S。

这个被选择的顶点是 Q 中拥有最小的 d[u] 值的顶点。当一个顶点 u 从 Q 中转移到了 S 中,算法对每条外接边 (u, v) 进行拓展。

后来我根据自己的理解,该算法基本可以分为这样几个步骤:

我用网上的一个图为例,说明该算法的执行过程。

下面来看代码:

void Dijkstra(MGraph g,int Vs,int *path,int *Dest)
{
int i,j,k;
EdgeType min;
int isshort[MAXVEX]; //初始化path前驱,Vs起始点到其他点的距离。
for (i =;i<g.numVexs;i++)
{
isshort[i]=;
path[i]=;
Dest[i]=g.Mat[Vs][i];
} //Vs选入isshort中
isshort[Vs]=;
//Vs到Vs的距离为0
Dest[Vs]=; for (i=;i<g.numVexs;i++)
{
//寻找当前最小的路径
min = IFY;
for (j=;j<g.numVexs;j++)
{
if (isshort[j] == && Dest[j] < min)
{
min = Dest[j];
k=j;
}
}
//把最小的标号记录,且该下标的顶点进入isshort
isshort[k]=; //在k为下标的顶点时候,寻找以k为起点,和k相连且没有归入到isshort中的点,
//Dest中存放的是 各个顶点到Vs点的最短距离。
//此时,如果通过K点到达各个点的距离还要小,则更新Dest数组。
for (j=;j<g.numVexs;j++)
{ if (isshort[j] == && ((min + g.Mat[k][j]) < Dest[j]) )
{
Dest[j]=min+g.Mat[k][j];
path[j]=k;
}
}
}
}

代码中的第一个for循环再第一幅图中表示。第二个for循环,依次为标号为1,。。。9的图。可以对着看。

完整代码:

// grp-dijkstra.cpp : 定义控制台应用程序的入口点。
// #include "stdafx.h"
#include <stdlib.h>
#include <string.h> #define MAXVEX 100
#define IFY 65535 typedef char VertexType;
typedef int EdgeType; bool g_visited[MAXVEX]; VertexType g_init_vexs[MAXVEX] = {'A','B','C','D','E','F','G','H','I'}; EdgeType g_init_edges[MAXVEX][MAXVEX] = {
{,,,IFY,IFY,IFY,IFY,IFY,IFY}, //'A'
{,,,,,IFY,IFY,IFY,IFY}, //'B'
{,,,IFY,,,IFY,IFY,IFY},//'C'
{IFY,,IFY,,,IFY,,IFY,IFY},//'D'
{IFY,,,,,,,,IFY}, //'E'
{IFY,IFY,,IFY,,,IFY,,IFY}, //'F'
{IFY,IFY,IFY,,,IFY,,,}, //'G'
{IFY,IFY,IFY,IFY,,,,,}, //'H'
{IFY,IFY,IFY,IFY,IFY,IFY,,,}, //'I'
}; //静态图-邻接矩阵
typedef struct {
VertexType vexs[MAXVEX];
EdgeType Mat[MAXVEX][MAXVEX];
int numVexs,numEdges;
}MGraph; //====================================================================
//打印矩阵
void prt_maxtix(EdgeType *p,int vexs)
{
int i,j;
for (i=;i<vexs;i++)
{
printf("\t");
for (j=;j<vexs;j++)
{
if( (*(p + MAXVEX*i + j)) == IFY)
{
printf(" $ ");
}
else
{
printf(" %2d ", *(p + MAXVEX*i + j));
}
}
printf("\n");
}
} //check the number of vextex
int getVexNum(VertexType *vexs)
{
VertexType *pos = vexs;
int cnt=;
while(*pos <= 'Z' && *pos >= 'A')
{
cnt++;
pos++;
}
return cnt;
} bool checkMat(EdgeType *p,VertexType numvex)
{
int i,j;
for (i=;i<numvex;i++)
{
for(j=i+;j<numvex;j++)
{
//printf("[%d][%d] = %d\t",i,j,*(p + MAXVEX*i + j));
//printf("[%d][%d] = %d\n",j,i,*(p + MAXVEX*j + i));
if (*(p + MAXVEX*i + j) != *(p + MAXVEX*j +i) )
{
printf("ERROR:Mat[%d][%d] or Mat[%d][%d] not equal!\n",i,j,j,i);
return false;
}
}
}
return true;
} void init_Grp(MGraph *g,VertexType *v,EdgeType *p)
{
int i,j;
// init vex num
(*g).numVexs = getVexNum(v); //init vexter
for (i=;i<(*g).numVexs;i++)
{
(*g).vexs[i]=*v;
v++;
} //init Mat
for (i=;i<(*g).numVexs;i++)
{
for (j=;j<(*g).numVexs;j++)
{
(*g).Mat[i][j] = *(p + MAXVEX*i + j);
}
}
if(checkMat(&((*g).Mat[][]),(*g).numVexs) == false)
{
printf("init error!\n");
getchar();
exit();
}
} void Dijkstra(MGraph g,int Vs,int *path,int *Dest)
{
int i,j,k;
EdgeType min;
int isshort[MAXVEX]; //初始化path前驱,Vs起始点到其他点的距离。
for (i =;i<g.numVexs;i++)
{
isshort[i]=;
path[i]=;
Dest[i]=g.Mat[Vs][i];
} //Vs选入isshort中
isshort[Vs]=;
//Vs到Vs的距离为0
Dest[Vs]=; for (i=;i<g.numVexs;i++)
{
//寻找当前最小的路径
min = IFY;
for (j=;j<g.numVexs;j++)
{
if (isshort[j] == && Dest[j] < min)
{
min = Dest[j];
k=j;
}
}
//把最小的标号记录,且该下标的顶点进入isshort
isshort[k]=; //在k为下标的顶点时候,寻找以k为起点,和k相连且没有归入到isshort中的点,
//Dest中存放的是 各个顶点到Vs点的最短距离。
//此时,如果通过K点到达各个点的距离还要小,则更新Dest数组。
for (j=;j<g.numVexs;j++)
{ if (isshort[j] == && ((min + g.Mat[k][j]) < Dest[j]) )
{
Dest[j]=min+g.Mat[k][j];
path[j]=k;
}
}
}
} int _tmain(int argc, _TCHAR* argv[])
{
MGraph grp;
EdgeType Dest[MAXVEX];
EdgeType Path[MAXVEX]; EdgeType edgeDest[MAXVEX][MAXVEX];
EdgeType edgePath[MAXVEX][MAXVEX]; int i; init_Grp(&grp,g_init_vexs,&g_init_edges[][]);
//prt_maxtix(&grp.Mat[0][0],grp.numVexs);
printf("Dijkstr start!\n");
for (i=;i<grp.numVexs;i++)
{
Dijkstra(grp,i,Path,Dest);
memcpy(edgeDest[i],Dest,grp.numVexs*sizeof(Dest[]));
memcpy(edgePath[i],Path,grp.numVexs*sizeof(Path[])); memset(Dest,,grp.numVexs*sizeof(Dest[]));
memset(Path,,grp.numVexs*sizeof(Path[]));
}
//Dijkstra(grp,0,Path,Dest);
printf("Dest vs to ve :\n");
prt_maxtix(&edgeDest[][],grp.numVexs); printf("Path matix :\n");
prt_maxtix(&edgePath[][],grp.numVexs); printf("finish\n");
getchar();
return ;
}

结果:

这个结果的意思是:

Dest vs to ve:

每一行为一个单独,比如第一行,表示V0到Vx的距离。与我们之前分析的第10幅图一样。

从这个表里面可以看出,任何一个点到另一个点的最短距离。

Path Matix:

最短路径所经过的点,对照第10幅图来看,就知道怎么线索路径,反一下就知道路径点。

这个可以看出,在主程序里面一个for

在Dijkstra中,for 中嵌套for,时间复杂度为O(N3)。(简化的粗估计)

对于大量的点,该方法效率会非常的低。因为对于每一个点,它都将遍历图中的其他每一个点。

算法学习记录-图——最短路径之Dijkstra算法的更多相关文章

  1. 算法学习记录-图——最小生成树之Kruskal算法

    之前的Prim算法是基于顶点查找的算法,而Kruskal则是从边入手. 通俗的讲:就是希望通过 边的权值大小 来寻找最小生成树.(所有的边称为边集合,最小生成树形成的过程中的顶点集合称为W) 选取边集 ...

  2. 算法学习记录-图——最小生成树之prim算法

    一个连通图的生成树是一个极小的连通子图,它包含图中全部的顶点(n个顶点),但只有n-1条边. 最小生成树:构造连通网的最小代价(最小权值)生成树. prim算法在严蔚敏树上有解释,但是都是数学语言,很 ...

  3. 算法学习记录-图——最小路径之Floyd算法

    floyd算法: 解决任意两点间的最短路径的一种算法,可以正确处理有向图或负权的最短路径问题,同时也被用于计算有向图的传递闭包. 设为从到的只以集合中的节点为中间节点的最短路径的长度. 若最短路径经过 ...

  4. 算法学习记录-图(DFS BFS)

    图: 目录: 1.概念 2.邻接矩阵(结构,深度/广度优先遍历) 3.邻接表(结构,深度/广度优先遍历) 图的基本概念: 数据元素:顶点 1.有穷非空(必须有顶点) 2.顶点之间为边(可空) 无向图: ...

  5. 算法学习记录-图——应用之关键路径(Critical Path)

    之前我们介绍过,在一个工程中我们关心两个问题: (1)工程是否顺利进行 (2)整个工程最短时间. 之前我们优先关心的是顶点(AOV),同样我们也可以优先关心边(同理有AOE).(Activity On ...

  6. 算法学习记录-图——应用之拓扑排序(Topological Sort)

    这一篇写有向无环图及其它的应用: 清楚概念: 有向无环图(DAG):一个无环的有向图.通俗的讲就是从一个点沿着有向边出发,无论怎么遍历都不会回到出发点上. 有向无环图是描述一项工程或者系统的进行过程的 ...

  7. 单源最短路径(dijkstra算法)php实现

    做一个医学项目,当中在病例评分时会用到单源最短路径的算法.单源最短路径的dijkstra算法的思路例如以下: 如果存在一条从i到j的最短路径(Vi.....Vk,Vj),Vk是Vj前面的一顶点.那么( ...

  8. 最短路径 | 深入浅出Dijkstra算法(一)

    参考网址: https://www.jianshu.com/p/8b3cdca55dc0 写在前面: 上次我们介绍了神奇的只有五行的 Floyd-Warshall 最短路算法,它可以方便的求得任意两点 ...

  9. 【算法设计与分析基础】25、单起点最短路径的dijkstra算法

    首先看看这换个数据图 邻接矩阵 dijkstra算法的寻找最短路径的核心就是对于这个节点的数据结构的设计 1.节点中保存有已经加入最短路径的集合中到当前节点的最短路径的节点 2.从起点经过或者不经过 ...

随机推荐

  1. 接口测试03 - Python HTTP库requests

    概述: 整理一些requests的相关知识,及如何使用requests进行接口测试. requests号称:是唯一的一个非转基因的Python HTTP库,人类可以安全享用. 安装: 先看下怎么安装r ...

  2. bootstrap 滚动监听 标签页 和 工具提示

    标签   <div class="container">     <h4>Tabs</h4>     <ul id="myTab ...

  3. SQL Server 2008添加字段成功,但提示列名无效

    在sql后查询,给现有表添加一个字段,即执行sql语句: alter table [sxrq_1108].[dbo].[公司周报表详情] add 总计 int default 0 然后在上述sql查语 ...

  4. (转)UVM挑战及概述

    UVM的调度也具有其独特的挑战,尤其是在调试的领域.其中的一些挑战如下: 1. Phase的管理:objections and synchronization 2. 线程调试 3. Tracing i ...

  5. [windows]命令行关机或重启电脑

    1.关机:菜单--〉运行--〉输入:cmd--〉输入:shutdown -s -t 0 2.重启:菜单--〉运行--〉输入:cmd--〉输入:shutdown -r -t 0 (注:“-r”代表重启, ...

  6. vue.js与react.js相比较的优势

    vue.js的简介 vue.js是一个javascript mvvm库,它是以数据驱动和组件化的思想构建的.我们平时多用js去操作dom,vue.js则是使用了数据绑定驱动来操作dom的,也就是说创建 ...

  7. Slacklining 2017/2/7

    原文 Proline Slacklining's expansion is still in process,but it already has a professional scene.Some ...

  8. 洛谷 P2264 情书

    题目背景 一封好的情书需要撰写人全身心的投入.lin_toto同学看上了可爱的卡速米想对她表白,但却不知道自己写的情书是否能感动她,现在他带着情书请你来帮助他. 题目描述 为了帮助lin_toto,我 ...

  9. 覆盖alert对话框-自制Jquery.alert插件

    Javascript 代码: (function ($) { 'use strict'; window.alert = $.alert = function (msg) { var defaultOp ...

  10. lua_to_luac

    #!/bin/sh `rm -rf allLua.zip` `mkdir ./tempScripts` `mkdir ./tempScripts/scripts` `cp -a ./scripts/ ...