有向有权图的最短路径算法--Dijkstra算法
Dijkstra算法
1.定义概览
Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法是很有代表性的最短路径算法,
在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等。注意该算法要求图中不存在负权边。
问题描述:在无向图 G=(V,E) 中,假设每条边 E[i] 的长度为 w[i],找到由顶点 V0 到其余各点的最短路径。(单源最短路径)
2.算法描述
首先把起点到所有点的路径花费都设为无穷大(起点到起点的花费设为0),对于一个没有被标记过的且在没有标记过的点中从起点到这个点的花费最小(最开始一定是起点)点v,设起点到这个点的花费为v.dist, 如果点v到与它相邻的点w满足v.dist + <v,w>.weight < w.dist,其中<v,w>.weight表示从v到w的权值,那么就令w.dist = v.dist + <v,w>.weight ,并把节点v标记(不要标记w),重复以上步骤,直到所有点被标记,所有点的i.dist就是起点到这个点所要的最小花费。
3 代码实现
按照上述思想,实现代码即可,图用邻接表表示。
#include <iostream>
using namespace std; #define Inf 65535
#define NotAVerter -1 /////////////////////邻接表的相关定义//////////////////////
typedef struct EdgeNode *position;
typedef struct Led_table* Table; struct EdgeNode //边表结点
{
int adjvex; // 邻接点域,存储该顶点对应的下标
int weight; // 对应边的权值
position next; // 链域,指向下一个邻接点
}; struct Led_table // 邻接表结构
{
int data; //邻接表的大小
position *firstedge; //边表头指针,可以理解为数组
}; //////////////////////////邻接表相关函数定义///////////////
Table Creat_Lable (int MaxElements) //MaxElements参数为希望创建的节点数
{ Table table1 = static_cast<Table> (malloc(sizeof(struct Led_table)));
table1->data = MaxElements;
if (table1 == NULL)
{
cout << "out of space!!!";
} table1->firstedge = static_cast<position*>(malloc(sizeof(position)*(table1->data)));
if (table1->firstedge == NULL)
{
cout << "out of space!!!";
} //给每个表头赋值,从0开始
for (int i = 0; i <= table1->data - 1; ++i)
{
table1->firstedge [i] = static_cast<position>(malloc(sizeof(EdgeNode))); //申请一个节点
if (table1->firstedge [i] == NULL)
{
cout << "out of space!!!";
}
table1->firstedge [i]->adjvex = 0; //表头这个参数存储入度
table1->firstedge [i]->weight = 0; //此参数在此时没有意义
table1->firstedge [i]->next = NULL; }
return table1; } void Insert (Table table1, int v, int w, int weig) //表示存在一条边为<v,w>,且权重为weig
{
position p = static_cast<position>(malloc(sizeof(EdgeNode))); //申请一个节点
if(p == NULL)
{
cout << "out of space!!!";
}
p->adjvex = w;
p->weight = weig;
p->next = table1->firstedge [v]->next;
table1->firstedge [v]->next = p; } /////////////////////单源无权算法相关定义/////////////////////////
typedef struct unweight_path *unweight_node ; struct unweight_path //
{
bool know;
int dist; // 邻接点域,存储该顶点对应的下标
int path; // 对应边的权值
}; unweight_node unweight_init(Table table1, int start) //节点初始化
{
unweight_node Node = static_cast<unweight_node>(malloc(sizeof(unweight_path)*(table1->data)));
if (Node == NULL)
{
cout << "out of space!!!";
}
for(int i = 0; i != table1->data; ++i)
{
Node[i].know = false;
Node[i].dist = Inf;
Node[i].path = NotAVerter;
}
Node[start].dist = 0;
return Node;
} ////////////////////////单源有权最短路径算法 Dijkstra ///////////////////////////// void Dijkstra_Algorithm (Table table1,unweight_node Node)
{
int v;
//用了两次for循环,时间复杂度较高
for (int j = 0; j != table1->data; ++j)
{
int zh = Inf;
for (int i = 0; i != table1->data; ++i) //找路径最小且没有标记过的点
{
if(!Node[i].know && zh > Node[i].dist ) //如果这个点是未知的,且距离比较小
{
zh = Node[i].dist;
v = i;
} }
//此时v是距离最小的那个点
Node[v].know = true; //标记这个点
position p = table1->firstedge [v]->next;
while (p != NULL) //与这个节点有连接的距离+1
{
if(!Node[p->adjvex].know && Node[v].dist + p->weight < Node[p->adjvex].dist )
{
Node[p->adjvex].dist = Node[v].dist + p->weight;
Node[p->adjvex].path = v;
}
p = p->next;
} } } /////////////////////打印实际的有权最短路径///////////////////////////////
//采用递归算法,从后往前推
void PrintPath (int v, unweight_node Node)
{
if(Node[v].path != NotAVerter)
{
PrintPath (Node[v].path ,Node);
cout << " -> "; }
cout << "v" << v;
} int main ()
{
Table table_1 = Creat_Lable (7); //创建一个大小为7的邻接表 //根据图来为邻接表插入数据 Insert (table_1, 0, 1, 2);Insert (table_1, 0, 2, 4);Insert (table_1, 0, 3, 1);
Insert (table_1, 1, 3, 3);Insert (table_1, 1, 4, 10);
Insert (table_1, 2, 5, 5);
Insert (table_1, 3, 2, 2);Insert (table_1, 3, 5, 8);Insert (table_1, 3, 6, 4);
Insert (table_1, 4, 3, 2);Insert (table_1, 4, 6, 6);
Insert (table_1, 6, 5, 1); unweight_node Node_1 = unweight_init(table_1, 0); //初始化节点 Dijkstra_Algorithm (table_1, Node_1);
for (int i = 0; i != table_1->data; ++i)
{
cout << Node_1[i].dist << '\t';
}
cout << endl;
PrintPath (6, Node_1);
while(1);
return 0;
}
对于下图来说
以v0为起点,到各点的最短路径为:
下面的v0->v3->v6表示v0到v6的最短路径经过的点。
Dijkstra算法是典型的贪婪算法,并不能保证100%的正确率。
也可参考 http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html 这篇博客的思想,本质上差不多。
夜深了.....
有向有权图的最短路径算法--Dijkstra算法的更多相关文章
- python数据结构与算法——图的最短路径(Dijkstra算法)
# Dijkstra算法——通过边实现松弛 # 指定一个点到其他各顶点的路径——单源最短路径 # 初始化图参数 G = {1:{1:0, 2:1, 3:12}, 2:{2:0, 3:9, 4:3}, ...
- 带权图的最短路径算法(Dijkstra)实现
一,介绍 本文实现带权图的最短路径算法.给定图中一个顶点,求解该顶点到图中所有其他顶点的最短路径 以及 最短路径的长度.在决定写这篇文章之前,在网上找了很多关于Dijkstra算法实现,但大部分是不带 ...
- 最短路径之Dijkstra算法及实例分析
Dijkstra算法迪科斯彻算法 Dijkstra算法描述为:假设用带权邻接矩阵来表示带权有向图.首先引进一个辅助向量D,它的每个分量D[i]表示当前所找到的从始点v到每个终点Vi的最短路径.它的初始 ...
- 最短路径算法-Dijkstra算法的应用之单词转换(词梯问题)(转)
一,问题描述 在英文单词表中,有一些单词非常相似,它们可以通过只变换一个字符而得到另一个单词.比如:hive-->five:wine-->line:line-->nine:nine- ...
- 数据结构与算法--最短路径之Dijkstra算法
数据结构与算法--最短路径之Dijkstra算法 加权图中,我们很可能关心这样一个问题:从一个顶点到另一个顶点成本最小的路径.比如从成都到北京,途中还有好多城市,如何规划路线,能使总路程最小:或者我们 ...
- 单源点最短路径的Dijkstra算法
在带权图(网)里,点A到点B所有路径中边的权值之和为最短的那一条路径,称为A,B两点之间的最短路径;并称路径上的第一个顶点为源点(Source),最后一个顶点为终点(Destination).在无权图 ...
- 最短路径 | 深入浅出Dijkstra算法(一)
参考网址: https://www.jianshu.com/p/8b3cdca55dc0 写在前面: 上次我们介绍了神奇的只有五行的 Floyd-Warshall 最短路算法,它可以方便的求得任意两点 ...
- 经典树与图论(最小生成树、哈夫曼树、最短路径问题---Dijkstra算法)
参考网址: https://www.jianshu.com/p/cb5af6b5096d 算法导论--最小生成树 最小生成树:在连通网的所有生成树中,所有边的代价和最小的生成树,称为最小生成树. im ...
- 单源最短路径(dijkstra算法)php实现
做一个医学项目,当中在病例评分时会用到单源最短路径的算法.单源最短路径的dijkstra算法的思路例如以下: 如果存在一条从i到j的最短路径(Vi.....Vk,Vj),Vk是Vj前面的一顶点.那么( ...
- 【算法设计与分析基础】25、单起点最短路径的dijkstra算法
首先看看这换个数据图 邻接矩阵 dijkstra算法的寻找最短路径的核心就是对于这个节点的数据结构的设计 1.节点中保存有已经加入最短路径的集合中到当前节点的最短路径的节点 2.从起点经过或者不经过 ...
随机推荐
- 关于设置Visaul Studio 2010 代码编辑界面背景的方法
1.打开代码编辑界面: 2.找到工具--选项: 3.打开选项后选中纯文本--项背景色: 4.点击自定义,找到自己需要的颜色: [注]: “项前景色”即代码的颜色: “项背景色”即背景颜色. 设置好后, ...
- 第23天:js-数据类型转换
一.padding1.内边距会影响盒子大小2.行内元素,尽量不用上下的padding和margin3.块元素嵌套块元素.子级会继承父级的宽度,高度由内容决定.如果给子级再设置padding,不会影响盒 ...
- JQuery UI的拖拽功能实现方法小结
JQuery UI提供的API极大简化了拖拽功能的开发.只需要分别在拖拽源(source)和目标(target)上调用draggable和droppable两个函数即可. 拖拽原理 首先要明确几个概念 ...
- InnoDB实现MVCC原理
MVCC(Multi-Version Concurrent Control),即多版本并发控制,通过保存数据在某个时间点的快照来实现,因此每个读操作都会看到一个一致性的视图,并且可以实现非阻塞的读 ...
- 【题解】CF#855 G-Harry Vs Voldemort
个人感觉挺有意思的,然而被颜神D无聊惹(- ̄▽ ̄)- 这题我们可以首先试图去统计以每一个点作为 w 点所能对答案造成的贡献是多少.不难发现,当且仅当 u 和 v 都在 w 所在边双的一侧的时候不能构成 ...
- bzoj 1862: [Zjoi2006]GameZ游戏排名系统 & bzoj 1056: [HAOI2008]排名系统
傻叉了一晚上,把t打成x,然后这题神奇在于输出一段数,不足的不用输出,一开始我的是直接找没有后面就退,然后这样会格式错误囧……然后最后zj的还卡了下空间,于是不用string就过了……string毁一 ...
- [TJOI2013]最长上升子序列 平衡树
其实是一道性质题. 首先观察到插入的数是递增的, 那么根据上升子序列的性质, 我们的非法情况就是统计到了在一个数前面的后插入的数, 但是由于插入的数是递增的,显然插入这个数后,这个数就是最大的,所以除 ...
- BZOJ3571 & 洛谷3236:[HNOI2014]画框——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=3571 https://www.luogu.org/problemnew/show/P3236 小T ...
- Git 常用操作(一)
使用git pull文件时和本地文件冲突: $ git stash $ git pull $ git stash pop stash@{0} [还原暂存的内容] 上传项目流程: pwd git p ...
- "HK"日常之冻结术
在那遥远的MSDN上,有那么一只被隐藏的函数,它掌管着Windows内核威力不容小觑~ 本教程仅作为学习研究,禁止其他用途! 富强.民主.文明.和谐, 自由.平等.公正.法治, 爱国.敬业.诚信.友善 ...