有向有权图的最短路径算法--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.从起点经过或者不经过 ...
随机推荐
- maven Tomcat idea 热部署
1.首先得有maven项目 2.配置tomcat,可以访问页面管理项目 修改: /conf/tomcat-users.xml <role rolename="manager-gui&q ...
- 分布式消息队列RocketMQ&Kafka -- 消息的“顺序消费”
在说到消息中间件的时候,我们通常都会谈到一个特性:消息的顺序消费问题.这个问题看起来很简单:Producer发送消息1, 2, 3... Consumer按1, 2, 3...顺序消费. 但实际情况却 ...
- java map的键是唯一的 所有 用set类型存放
- 《转》vue-cli的webpack模板项目配置文件注释
一.文件结构 本文主要分析开发(dev)和构建(build)两个过程涉及到的文件,故下面文件结构仅列出相应的内容. ├─build │ ├─build.js │ ├─check-versions.js ...
- Unable to open connection to "Microsoft SQL Server, provider V1.0.5000.0 in framework
解决办法:1 以管理员身份登陆2 找到ORACLE_HOME文件夹(D:\oracle\ora92),点右键,选属性——安全,在组或用户栏中选"Authenticated Users&quo ...
- 【hackerrank】Week of Code 30
Candy Replenishing Robot Find the Minimum Number 直接模拟 Melodious password dfs输出方案 Poles 题意:有多个仓库,只能从后 ...
- POJ1523:SPF——题解
http://poj.org/problem?id=1523 这题明显就是求割点然后求割完之后的强连通分量的个数. 割点都会求,怎么求割完的分量个数呢? 我们可以通过万能的并查集啊!(具体做法看代码吧 ...
- BZOJ4873:[SHOI2017]寿司餐厅——题解
http://www.lydsy.com/JudgeOnline/problem.php?id=4873 https://www.luogu.org/problemnew/show/P3749 简要题 ...
- ZOJ2314:Reactor Cooling——题解
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1314 题目大意:无源汇上下界网络流,问每个管子走多少流量才能满足所有管子的下界 ...
- [Leetcode] single number 找单个数
Given an array of integers, every element appears twice except for one. Find that single one. Note: ...