最短路径之迪杰斯特拉(Dijkstra)算法

对于网图来说,最短路径,是指两顶点之间经过的边上权值之和最少的路径,并且我们称路径上的第一个顶点为源点,最后一个顶点为终点。最短路径的算法主要有迪杰斯特拉(Dijkstra)算法和弗洛伊德(Floyd)算法。本文先来讲第一种,从某个源点到其余各顶点的最短路径问题。

这是一个按路径长度递增的次序产生最短路径的算法,它的大致思路是这样的。

初始时,S中仅含有源。设u是G的某一个顶点,把从源到u且中间只经过S中顶点的路称为从源到u的特殊路径,并用数组dist记录当前每个顶点所对应的最短特殊路径长度。Dijkstra算法每次从V-S中取出具有最短特殊路长度的顶点u,将u添加到S中,同时对数组dist作必要的修改。一旦S包含了所有V中顶点,dist就记录了从源到所有其它顶点之间的最短路径长度.

比如说要求图7-7-3中顶点v0到v1的最短路径,显然就是1。由于顶点v1还与v2,v3,v4连线,所以此时我们同时求得了v0->v1->v2
= 1+3 = 4, v0->v1->v3 = 1 +7 = 8, v0->v1->v4 = 1+5 = 6。

现在我们可以知道v0到v2的最短距离为4而不是v0->v2
直接连线的5,如图7-7-4所示。由于顶点v2还与v4,v5连线,所以同时我们求得了v0->v2->v4其实就是v0->v1->v2->v4
= 4+1=5,v0->v2->v5 = 4+7 =
11,这里v0->v2我们用的是刚才计算出来的较小的4。此时我们也发现v0->v1->v2->v4 =
5要比v0->v1->v4 = 6还要小,所以v0到v4的最短距离目前是5,如图7-7-5所示。

当我们要求v0到v3的最短路径时,通向v3的三条边,除了v6没有研究过外,v0->v1->v3
= 8, 而v0->v4->v3 = 5 +2 = 7,因此v0到v3的最短路径为7,如图7-7-6所示。

如上所示,这个算法并不是一下子就求出来v0到v8的最短路径,而是一步步求出它们之间顶点的最短距离,过程中都是基于已经求出的最短路径的基础上,求得更远顶点的最短路径,最终得到想要的结果。


#include <iostream>
using namespace std;

const int maxnum = 100;
const int maxint = 999999;

// 各数组都从下标1开始
int dist[maxnum]; // 表示当前点到源点的最短路径长度
int prev[maxnum]; // 记录当前点的前一个结点
int c[maxnum][maxnum]; // 记录图的两点间路径长度
int n, line; // 图的结点数和路径数

// n -- n nodes
// v -- the source node
// dist[] -- the distance from the ith node to the source node
// prev[] -- the previous node of the ith node
// c[][] -- every two nodes‘ distance
void Dijkstra(int n, int v, int *dist, int *prev, int c[maxnum][maxnum])
{
bool s[maxnum]; // 判断是否已存入该点到S集合中
for(int i=1; i<=n; ++i)
{
dist[i] = c[v][i];
s[i] = 0; // 初始都未用过该点
if(dist[i] == maxint)
prev[i] = 0;
else
prev[i] = v;
}
dist[v] = 0;
s[v] = 1;

// 依次将未放入S集合的结点中,取dist[]最小值的结点,放入结合S中
// 一旦S包含了所有V中顶点,dist就记录了从源点到所有其他顶点之间的最短路径长度
// 注意是从第二个节点开始,第一个为源点
for(int i=2; i<=n; ++i)
{
int tmp = maxint;
int u = v;
// 找出当前未使用的点j的dist[j]最小值
for(int j=1; j<=n; ++j)
if((!s[j]) && dist[j]<tmp)
{
u = j; // u保存当前邻接点中距离最小的点的号码
tmp = dist[j];
}
s[u] = 1; // 表示u点已存入S集合中

// 更新dist
for(int j=1; j<=n; ++j)
if((!s[j]) && c[u][j]<maxint)
{
int newdist = dist[u] + c[u][j];
if(newdist < dist[j])
{
dist[j] = newdist;
prev[j] = u;
}
}
}
}

// 查找从源点v到终点u的路径,并输出
void searchPath(int *prev,int v, int u)
{
int que[maxnum];
int tot = 1;
que[tot] = u;
tot++;
int tmp = prev[u];
while(tmp != v)
{
que[tot] = tmp;
tot++;
tmp = prev[tmp];
}
que[tot] = v;
for(int i=tot; i>=1; --i)
if(i != 1)
cout << que[i] << " -> ";
else
cout << que[i] << endl;
}

int main()
{
freopen("input.txt", "r", stdin);
// 各数组都从下标1开始

// 输入结点数
cin >> n;
// 输入路径数
cin >> line;
int p, q, len; // 输入p, q两点及其路径长度

// 初始化c[][]为maxint
for(int i=1; i<=n; ++i)
for(int j=1; j<=n; ++j)
c[i][j] = maxint;

for(int i=1; i<=line; ++i)
{
cin >> p >> q >> len;
if(len < c[p][q]) // 有重边
{
c[p][q] = len; // p指向q
c[q][p] = len; // q指向p,这样表示无向图
}
}

for(int i=1; i<=n; ++i)
dist[i] = maxint;
for(int i=1; i<=n; ++i)
{
for(int j=1; j<=n; ++j)
printf("%8d", c[i][j]);
printf("\n");
}

Dijkstra(n, 1, dist, prev, c);

// 最短路径长度
cout << "源点到最后一个顶点的最短路径长度: " << dist[n] << endl;

// 路径
cout << "源点到最后一个顶点的路径为: ";
searchPath(prev, 1, n);
}

输入数据:
5
7
1 2
10
1
4 30
1
5 100
2
3 50
3
5 10
4
3 20
4
5 60
输出数据:
999999 10
999999 30 100
10 999999 50 999999 999999
999999 50 999999 20 10
30
999999 20 999999 60
100 999999 10 60 999999
源点到最后一个顶点的最短路径长度:
60
源点到最后一个顶点的路径为: 1 -> 4 -> 3 -> 5

参考:http://tech.ddvip.com/2013-06/1371580493197421.html

http://www.wutianqi.com/?p=1890

最短路径之迪杰斯特拉(Dijkstra)算法,布布扣,bubuko.com

时间: 2024-11-08 22:33:05

最短路径之迪杰斯特拉(Dijkstra)算法的相关文章

43. 蛤蟆的数据结构笔记之四十三最短路径之迪杰斯特拉(Dijkstra )算法

43. 蛤蟆的数据结构笔记之四十三最短路径之迪杰斯特拉(Dijkstra )算法 本篇名言:"辛勤的蜜蜂永没有时间悲哀.--布莱克" 这次来看下Dijkstra )算法.还是老方法,先原理,后实现.代码来自网络. 欢迎转载,转载请标明出处:http://blog.csdn.net/notbaron/article/details/47046031 1.  最短路径 最短路径问题是图论研究中的一个经典算法问题, 旨在寻找图(由结点和路径组成的)中两结点之间的最短路径. 管道铺设.线路安排

[C++]单源最短路径:迪杰斯特拉(Dijkstra)算法(贪心算法)

1 Dijkstra算法 1.1 算法基本信息 解决问题/提出背景 单源最短路径(在带权有向图中,求从某顶点到其余各顶点的最短路径) 算法思想 贪心算法 按路径长度递增的次序,依次产生最短路径的算法 [适用范围]Dijkstra算法仅适用于[权重为正]的图模型中 时间复杂度 O(n^3) 补充说明 亦可应用于[多源最短路径](推荐:Floyd算法(动态规划,O(n^3))) Dijkstra 时间复杂度:O(n^3) 1.2 算法描述 1.2.1 求解过程(具体思路) 1.2.2 示例 1.2

C# 迪杰斯特拉(Dijkstra)算法

Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止. 其基本思想是,设置顶点集合S并不断地作贪心选择来扩充这个集合.一个顶点属于集合S当且仅当从源到该顶点的最短路径长度已知. 初始时,S中仅含有源.设u是G的某一个顶点,把从源到u且中间只经过S中顶点的路称为从源到u的特殊路径,并用数组dist记录当前每个顶点所对应的最短特殊路径长度.Dijkstra算法每次从V-S中取出具有最短特殊路长度

迪杰斯特拉(Dijkstra)算法

1 # include <stdio.h> 2 3 # define MAX_VERTEXES 20//最大顶点数 4 # define INFINITY 65535;//代表∞ 5 6 typedef struct 7 {/* 无向图结构体 */ 8 int vexs[MAX_VERTEXES];//顶点下标 9 int arc[MAX_VERTEXES][MAX_VERTEXES];//矩阵 10 int numVertexes, numEdges;//顶点数和边数 11 12 }MGra

迪杰斯特拉(Dijkstra)算法求最短路径

我用的是邻接矩阵来存储图的. 代码如下: void Graph:: Dijkstra(){ struct DijNode{ int index; int distance; vector<string> path; bool Founded; //判定是否找到了... }; DijNode*shorestPaths=new DijNode[mgraph.vexnum]; string startPoint; int startIndex; cout<<"请输入单源点:&q

迪杰斯特拉/dijkstra 算法模板(详细注释)

#include <iostream> #include <malloc.h> #include <cstring> #include <stack> #include <cstdio> //定义邻接矩阵的大小 #define N 100 #define M 100 using namespace std; typedef struct node { int map[N][M];//邻接矩阵 int n;//顶点数 int e;//边数 }MGr

迪杰斯特拉/dijkstra 算法模板(具体凝视)

#include <iostream> #include <malloc.h> #include <cstring> #include <stack> #include <cstdio> //定义邻接矩阵的大小 #define N 100 #define M 100 using namespace std; typedef struct node { int map[N][M];//邻接矩阵 int n;//顶点数 int e;//边数 }MGr

数据结构之最短路径(1) [迪杰斯特拉算法]

迪杰斯特拉算法介绍: 迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径. 它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止. 基本思想: 通过Dijkstra计算图G中的最短路径时,需要指定起点s(即从顶点s开始计算). 此外,引进两个集合S和U.S的作用是记录已求出最短路径的顶点(以及相应的最短路径长度),而U则是记录还未求出最短路径的顶点(以及该顶点到起点s的距离). 初始时,S中只有起点s:U中是除s之外的顶点,并且

最短路径之迪杰斯特拉与双向迪杰斯特拉实验结果

1.  实验数据 数据集:City of Oldenburg (OL) Road Network 9组查询均为相距较远的结点 2. 实验结果一 最近一直在围绕双向迪杰斯特拉转,对其中重要的优先队列数据结构,尝试了用无索引的二叉堆实现.有索引的二叉堆实现以及无索引的斐波那契实现三种方式.其中无索引的优先队列允许出现相同的节点,而有索引的优先队列中不允许.不同实现方式运行时间如表2-1所示,其中每个查询都运行了10000次,单位ms. 表2-1 双向迪杰斯特拉不同优先队列实现方式运行结果 查询 双向