最短路径算法—Dijkstra(迪杰斯特拉)算法分析与实现(C/C++)及其他 + leetcode习题实践
2016-12-17 01:54
1006 查看
最短路径求解
最短路径的常用解法有迪杰克斯特拉算法Dijkstra Algorithm, 弗洛伊德算法Floyd-Warshall Algorithm, 和贝尔曼福特算法Bellman-Ford Algorithm,其中,Floyd算法是多源最短路径,即求任意点到任意点到最短路径,而Dijkstra算法和Bellman-Ford算法是单源最短路径,即单个点到任意点到最短路径。
单源最短路径(无负权值):
Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法能得出最短路径的最优解,但由于它遍历计算的节点很多,所以效率低。Dijkstra算法是很有代表性的最短路算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等。
其基本思想是,设置顶点集合S并不断地作贪心选择来扩充这个集合。一个顶点属于集合S当且仅当从源到该顶点的最短路径长度已知。
初始时,S中仅含有源。设u是G的某一个顶点,把从源到u且中间只经过S中顶点的路称为从源到u的特殊路径,并用数组dist记录当前每个顶点所对应的最短特殊路径长度。Dijkstra算法每次从V-S中取出具有最短特殊路长度的顶点u,将u添加到S中,同时对数组dist作必要的修改。一旦S包含了所有V中顶点,dist就记录了从源到所有其它顶点之间的最短路径长度。
代码实现
// AllTest.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <iostream> #include <string.h> #include <stdio.h> #include <algorithm> #include <stack> using namespace std; #define INT_MAX1 999999 typedef struct MGraph { int n,line; int m[100][100]; }gg,*pG; // g -- adjacent matrix pointer // v0 -- the source node // dist[] -- the distance from the ith node to the source node // prev[] -- the previous node of the ith node void Dijkstra (pG g,int *pre,int *dis,int v0) { bool visited[100]; // 判断是否已存入该点到S集合中 int n=g->n; for (int i=1;i<=n;i++) { dis[i]=g->m[v0][i]; //初始dis visited[i]=false; // 初始都未用过该点 if (dis[i]==INT_MAX1) //初始pre pre[i]=0; else pre[i]=v0; } visited[v0]=true; //初始起点 dis[v0]=0; // 依次将未放入S集合的结点中,取dis[]最小值的结点,放入结合S中 // 一旦S包含了所有V中顶点,dis就记录了从源点到所有其他顶点之间的最短路径长度 // 注意是从第二个节点开始,第一个为源点 for (int i=2;i<=g->n;i++) //1 { int u=v0,min=INT_MAX1; // 找出当前未使用的点j的dis[j]最小值 for (int j=1;j<=g->n;j++) // if (!visited[j]&&dis[j]<min) { u=j; // u保存当前邻接点中距离最小的点的号码 min=dis[j]; } visited[u]=true; dis[u]=min;//其实这个不需要再赋值 //更新dis for (int j=1;j<=g->n;j++) if (!visited[j]&&g->m[u][j]<INT_MAX1&&dis[u]+g->m[u][j]<dis[j]) { pre[j]=u; dis[j]=dis[u]+g->m[u][j]; } } } // 查找从源点v到终点u的路径,并输出 void research(pG g,int *pre,int v0,int u) { int t=pre[u]; stack<int> s; s.push(u); while (t!=v0) { s.push(t); t=pre[t]; } s.push(v0); while (!s.empty()) { int output=s.top(); s.pop(); if (output==v0) cout<<v0; else cout<<"->"<<output; } } int main() { MGraph g; freopen("input.txt","r",stdin); cin>>g.n; cin>>g.line; for (int i=1;i<=g.n;i++) for (int j=1;j<=g.n;j++) g.m[i][j]=INT_MAX1; int dis[100]; generate(dis,dis+100,[](){return INT_MAX1;}); int pre[100]; generate(pre,pre+100,[](){return 1;}); for (int i=1;i<=g.line;i++) { int x,y,weight; cin>>x>>y>>weight; g.m[x][y]=weight; //g.m[y][x]=weight;//无向图 } for(int i=1; i<=g.n; ++i) { for(int j=1; j<=g.n; ++j) printf("%8d", g.m[i][j]); printf("\n"); } Dijkstra(&g,pre,dis,1); cout<<"源点到最后一个顶点的最短路径长度: "<< dis[g.n] << endl; // 路径 cout << "源点到最后一个顶点的路径为: "; research(&g,pre,1,g.n); return 0; }
数据
5
7
1 2 10
1 4 30
1 5 100
2 3 50
3 5 10
4 3 20
4 5 60
单源最短路径(有负权值)
任意两点最短路径
LeetCode 743. Network
Delay Time
DesciptionThere are
Nnetwork nodes, labelled
1to
N.
Given
times, a list of travel times as directed edges
times[i] = (u, v, w), where
uis the source node,
vis
the target node, and
wis the time it takes for a signal to travel from source to target.
Now, we send a signal from a certain node
K. How long will it take for all nodes to receive the signal?
If it is impossible, return
-1.
Note:
Nwill be in the range
[1, 100].
Kwill be in the range
[1, N].
The length of
timeswill be in the range
[1, 6000].
All edges
times[i] = (u, v, w)will have
1 <= u, v <= Nand
1 <= w <= 100.
解题思路:
基于Bellman-Ford算法的解法,时间复杂度是O(VE),V和E分别是结点和边的个数。这种算法是基于DP来求全局最优解,原理是对图进行V- 1次松弛操作,这里的V是所有结点的个数(为啥是V-1次呢,因为最短路径最多只有V-1条边,所以只需循环V-1次),在重复计算中,使得每个结点的距离被不停的更新,直到获得最小的距离,这种设计方法融合了暴力搜索之美,写法简洁又不失优雅。之前提到了,Bellman-Ford算法可以处理负权重的情况,但是不能有负环存在,一般形式的写法中最后一部分是检测负环的,如果存在负环则报错。不能有负环原因是,每转一圈,权重和都在减小,可以无限转,那么最后的最小距离都是负无穷,无意义了。没有负环的话,V-1次循环后各点的最小距离应该已经收敛了,所以在检测负环时,就再循环一次,如果最小距离还能更新的话,就说明存在负环。这道题由于不存在负权重,所以就不检测了。
class Solution { public://最短路径中的最大值 int networkDelayTime(vector<vector<int>>& times, int N, int K) { vector<int> dist(N+1,INT_MAX); dist[K]=0; for (int i=1;i<N;++i) for (auto e:times){ int u=e[0],v=e[1],w=e[2]; if (dist[u]!=INT_MAX&&dist[u]+w<dist[v])//update edge of u vertex dist[v]=dist[u]+w; } int max=0; for (int i=1;i<=N;++i) max=(dist[i]>max?dist[i]:max); return max==INT_MAX?-1:max; } };
参考网址:http://developer.51cto.com/art/201105/262210.htm
相关文章推荐
- 最短路径算法—Dijkstra(迪杰斯特拉)算法分析与实现(C/C++)
- 最短路径算法—Dijkstra(迪杰斯特拉)算法分析与实现(C/C++)
- 最短路径算法—Dijkstra(迪杰斯特拉)算法分析与实现(C/C++)
- 最短路径算法—Dijkstra(迪杰斯特拉)算法分析与实现(C/C++)
- 最短路径算法—Dijkstra(迪杰斯特拉)算法分析与实现(C/C++)
- 最短路径算法—Dijkstra(迪杰斯特拉)算法分析与实现(C/C++)
- 最短路径算法—Dijkstra(迪杰斯特拉)算法分析与实现(C/C++)
- [转]最短路径算法—Dijkstra(迪杰斯特拉)算法分析与实现
- 最短路径算法—Dijkstra(迪杰斯特拉)算法分析与实现(C/C++)
- 最短路径算法—Dijkstra(迪杰斯特拉)算法分析与实现(C/C++)
- 最短路径算法—Dijkstra(迪杰斯特拉)算法分析与实现(C/C++)
- 最短路径算法—Dijkstra(迪杰斯特拉)算法分析与实现(Python)
- 最短路径算法—Dijkstra(迪杰斯特拉)算法分析与实现(C/C++)
- 最短路径算法—Dijkstra(迪杰斯特拉)算法分析与实现代码(C/C++)
- 最短路径算法—Dijkstra(迪杰斯特拉)算法分析与实现(C/C++)
- 算法实现Java之最短路径迪杰斯特拉(Dijkstra)
- Dijkstra [迪杰斯特拉]算法思路(求单点到其他每个点的各个最短路径)Floyd算法:任意两点间最短距离
- 迪杰斯特拉(Dijkstra)算法求解单源最短路径及其相应长度(java实现)
- 数据结构之---C语言实现最短路径之Dijkstra(迪杰斯特拉)算法
- Java实现求最短路径算法——————Dijkstra(迪杰斯特拉)