算法学习 - Dijkstra(迪杰斯特拉)算法学习
来源:互联网 发布:浩浩乎如冯虚御风的乎 编辑:程序博客网 时间:2024/06/06 08:53
Dijkstra算法
其实Dijkstra是单源点最短路径的基础算法,这个算法的目的就是找到一个图中的某个点V到这个图中其他点的最短路径。
条件
- 有向图
- 没有负权值路径
时间复杂度:O(E) + O(V^2) = O(V^2)
当图是稠密的时候和稀疏的时候时间复杂度还是有点差别的。
原理
原理是这样的,首先最开始所有节点都是未知的,距离未知,初始化起始节点的距离为0, 其他节点都是不可达(用最大整数,或者-1表示)。然后每次找到所有未知节点中距离最小的那个节点(minNode 节点),标记为已知,已这个节点为起始,松弛所有挨着它的节点。
依次类推,每次都找所有未知节点中距离最小的节点。标记为已知,然后松弛操作。
代码实现
其实这个还挺简单的,单源点最短路径还有一个Bellman-Ford算法,以后在写,比较简单。
Dijkstra算法:
//// main.cpp// Dijkstra//// Created by Alps on 15/3/4.// Copyright (c) 2015年 chen. All rights reserved.//#include <iostream>#ifndef NumVertex#define NumVertex 4 //定义图的顶点数量#endif#ifndef Infinity#define Infinity 10000 //定义权值最大值#endifusing namespace std;typedef int Vertex;struct LinkList{ //定义邻接链表 int val; int length; LinkList * next; LinkList(int v): val(v), next(NULL) {}};typedef LinkList* List;struct TableEntry{ //定义结构体用来实现算法。 List Header; bool Know; int Dist; Vertex Path;};typedef struct TableEntry Table[NumVertex+1]; //定义结构体所存储的图void InitTable(Vertex Start, Table T){ //初始化 List temp; int OutDegree; for (int i = 1; i <= NumVertex; i++) { T[i].Know = false; T[i].Dist = Infinity; T[i].Path = -1; T[i].Header = NULL; scanf("%d",&OutDegree); for (int j = 0; j < OutDegree; j++) { temp = (List)malloc(sizeof(struct LinkList)); scanf("%d %d",&(temp->val), &(temp->length)); temp->next = T[i].Header; T[i].Header = temp; } } T[Start].Dist = 0;}void PrintPath (Vertex V,Table T){ //打印路径 if (T[V].Path != -1) { PrintPath(T[V].Path, T); printf(" to "); } printf("%d", V);}Vertex SmallDistUnknow(Table T){ //查找当前已知顶点到未知顶点路径的最小值 int MinDist = Infinity + 1, V = 0; for (int i = 1; i <= NumVertex; i++) { if (!T[i].Know && T[i].Dist <= MinDist) { MinDist = T[i].Dist; V = i; } } return V;}void Dijkstra(Table T){ //算法主题 List temp; Vertex V; while (1) { V = SmallDistUnknow(T); if (V == 0) { break; } T[V].Know = true; temp = T[V].Header; while (temp != NULL) { if (!T[temp->val].Know) { if (T[V].Dist + temp->length < T[temp->val].Dist) { T[temp->val].Dist = T[V].Dist + temp->length; T[temp->val].Path = V; } } temp = temp->next; } }}int main(int argc, const char * argv[]) { Table T; InitTable(1, T); Dijkstra(T); PrintPath(2, T);// std::cout << "Hello, World!\n"; return 0;}
二维数组实现
最近在刷题,刚好有个用邻接矩阵存图的方式实现了一下,所以可以参考一下。
原理一样,只不过存放的时候,用了一个flag表示了节点是否已知,用了len数组存放起点到这些节点的距离。
//// main.cpp// HiHocoder//// Created by Alps on 16/5/9.// Copyright © 2016年 chen. All rights reserved.//#include <iostream>#include <cstring>#include <string>using namespace std;long long dist[1002][1002];int flag[1002];long long len[1002];long long minNum(long long a, long long b){ if(a == -1) return b; return a < b ? a : b;}int minNode(int N){ long long minnum = -1; int nodenum = -1; for(int i = 1; i <= N; i++){ if(flag[i] == -1 && len[i] != -1){ if(minnum == -1 || minnum >= len[i]){ minnum = len[i]; nodenum = i; } } } return nodenum;}void dijkstra(long long dist[][1002], int N, int S){ len[S] = 0; while(1){ int cur = minNode(N); if(cur == -1) return; flag[cur] = 0; for(int i = 1; i <= N; i++){ if(dist[cur][i] == -1) continue; len[i] = minNum(len[i], dist[cur][i] + len[cur]); } }}int main(){ int N,M,S,T; while(cin>>N>>M>>S>>T){ for(int i = 0; i <= N; i++){ for(int j = 0; j <= N; j++){ dist[i][j] = -1; if(i == j){ dist[i][j] = 0; } } flag[i] = -1;//初始化为-1表示未知 len[i] = -1; //初始化距离为-1 表示无穷大 } int x, y , d; for(int i = 0; i < M; i++){ cin>>x>>y>>d; dist[x][y] = minNum(dist[x][y], d); dist[y][x] = dist[x][y]; //无向图,有向图的话,去掉这行代码 } dijkstra(dist, N, S); cout<<len[T]<<endl; } return 0;}
测试数据:
5 23 5 4 //5是节点数量,id 1-5, 23是边数量,5是起点id,4是终点id
1 2 708 //起点到终点 距离
2 3 112
3 4 721
4 5 339
5 4 960
1 5 849
2 5 98
1 4 99
2 4 25
2 1 200
3 1 146
3 2 106
1 4 860
4 1 795
5 4 479
5 4 280
3 4 341
1 4 622
4 2 362
2 3 415
4 1 904
2 1 716 //无向图,但是会出现同样节点,多条路
2 5 575
0 0
- 算法学习 - Dijkstra(迪杰斯特拉)算法学习
- Dijkstra(迪杰斯特拉)算法学习
- Dijkstra算法学习笔记
- Dijkstra算法再学习
- Dijkstra算法 学习笔记
- Dijkstra算法学习
- Dijkstra算法 学习笔记
- Dijkstra算法学习笔记(1)
- 算法学习 - Dijkstra's Algorithm
- 算法学习 - Dijkstra's Algorithm
- 最短路算法dijkstra算法学习
- Dijkstra(迪杰斯特拉)算法
- Dijkstra(迪杰斯特拉)算法
- 迪杰斯特拉算法(Dijkstra)
- 算法复习 - Dijkstra算法(迪杰斯特拉算法)
- 单源最短路径dijkstra算法的初步学习(1)
- Dijkstra算法(最短单源路径)学习笔记
- [算法导论] 单源最短路径 - Dijkstra 学习笔记
- web的情人节(我待你如初恋,你却虐我千百遍)
- MarkDown语法
- C 语言中switch语法的用处
- Creating Excel2013-style-toolbar in Excel2010 (Excel VBA)
- JSP不支持EL表达式的解决方案
- 算法学习 - Dijkstra(迪杰斯特拉)算法学习
- 矩阵
- HttpClient
- 各种windows操作系统安装文件,办公软件安装地址大全
- CSS简单表格样式
- C/C++ Volatile关键词深度剖析
- Material Design 之 侧边栏与 SystemBar 不得不说的故事
- 为什么匿名内部类参数必须为final类型
- Linux中断(interrupt)子系统之三:中断流控处理层