图算法-Dijkstra算法
目录
- 图算法-Dijkstra算法
- 图算法-Floyd算法
- 图算法-Bellman-Ford算法
- 图算法-Prim算法
- 图算法-Kruskal算法
参考文献
1 问题分析
2 算法原理
通过Dijkstra计算图G中的最短路径时,需要指定起点s(即从顶点s开始计算)。
此外,引进两个集合S和U。S的作用是记录已求出最短路径的顶点(以及相应的最短路径长度),而U则是记录还未求出最短路径的顶点(以及该顶点到起点s的距离)。
初始时,S中只有起点s;U中是除s之外的顶点,并且U中顶点的路径是”起点s到该顶点的路径”。
然后,从U中找出路径最短的顶点,并将其加入到S中;
接着,更新U中的顶点和顶点对应的路径。
然后,再从U中找出路径最短的顶点,并将其加入到S中;接着,更新U中的顶点和顶点对应的路径。 … 重复该操作,直到遍历完所有顶点。
3 算法步骤
基本步骤
初始时,S只包含起点s;U包含除s外的其他顶点,且U中顶点的距离为”起点s到该顶点的距离”[例如,U中顶点v的距离为(s,v)的长度,然后s和v不相邻,则v的距离为∞]。
从U中选出”距离最短的顶点k”,并将顶点k加入到S中;同时,从U中移除顶点k。
更新U中各个顶点到起点s的距离。之所以更新U中顶点的距离,是由于上一步中确定了k是求出最短路径的顶点,从而可以利用k来更新其它顶点的距离;例如,(s,v)的距离可能大于(s,k)+(k,v)的距离。
重复步骤(2)和(3),直到遍历完所有顶点。
图解过程

详细说明
初始状态:S是已计算出最短路径的顶点集合,U是未计算除最短路径的顶点的集合!
第1步:将顶点D加入到S中。
此时,S={D(0)}, U={A(∞),B(∞),C(3),E(4),F(∞),G(∞)}。 注:C(3)表示C到起点D的距离是3。
第2步:将顶点C加入到S中。
上一步操作之后,U中顶点C到起点D的距离最短;因此,将C加入到S中,同时更新U中顶点的距离。以顶点F为例,之前F到D的距离为∞;但是将C加入到S之后,F到D的距离为9=(F,C)+(C,D)。
此时,S={D(0),C(3)}, U={A(∞),B(23),E(4),F(9),G(∞)}。
第3步:将顶点E加入到S中。
上一步操作之后,U中顶点E到起点D的距离最短;因此,将E加入到S中,同时更新U中顶点的距离。还是以顶点F为例,之前F到D的距离为9;但是将E加入到S之后,F到D的距离为6=(F,E)+(E,D)。
此时,S={D(0),C(3),E(4)}, U={A(∞),B(23),F(6),G(12)}。
第4步:将顶点F加入到S中。
此时,S={D(0),C(3),E(4),F(6)}, U={A(22),B(13),G(12)}。
第5步:将顶点G加入到S中。
此时,S={D(0),C(3),E(4),F(6),G(12)}, U={A(22),B(13)}。
第6步:将顶点B加入到S中。
此时,S={D(0),C(3),E(4),F(6),G(12),B(13)}, U={A(22)}。
第7步:将顶点A加入到S中。
此时,S={D(0),C(3),E(4),F(6),G(12),B(13),A(22)}。
此时,起点D到各个顶点的最短距离就计算出来了:A(22) B(13) C(3) D(0) E(4) F(6) G(12)。
4 算法效率
时间复杂度$O(n^2)$
5 算法实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
| #include<iostream> #include<vector> using namespace std;
class Graph{ private: int vertex_num; int edge; vector<vector<int>> arc; public: Graph(); Graph(int vertex_num_,int edge_); void print_edge(); void print_arc(); void Dijkstra(int begin); void Floyd(); void Prim(); void Kruskal(); };
Graph::Graph(){ this->vertex_num = 7; this->edge=12; this->arc = vector<vector<int>>(vertex_num,vector<int>(vertex_num,INT_MAX)); arc[0][1]=12; arc[1][0]=12; arc[0][6]=14; arc[6][0]=14; arc[0][5]=16; arc[5][0]=16; arc[1][2]=10; arc[2][1]=10; arc[1][5]=7; arc[5][1]=7; arc[2][3]=3; arc[3][2]=3; arc[2][4]=5; arc[4][2]=5; arc[2][5]=6; arc[5][2]=6; arc[3][4]=4; arc[4][3]=4; arc[4][5]=2; arc[5][4]=2; arc[4][6]=8; arc[6][4]=8; arc[5][6]=9; arc[6][5]=9; for(int i=0;i<vertex_num;i++){ arc[i][i]=0; } }
Graph::Graph(int vertex_num_,int edge_){ this->vertex_num=vertex_num_; this->edge=edge_; this->arc=vector<vector<int>>(vertex_num,vector<int>(vertex_num,INT_MAX)); int beg=0,end=0,weight=0; for(int i=0;i<edge_;i++){ cin>>beg>>end>>weight; arc[beg][end]=weight; arc[end][beg]=weight; } }
void Graph::print_edge(){ for(int i=0;i<vertex_num;i++){ for(int j=0;j<vertex_num;j++){ if(arc[i][j]<INT_MAX) cout<<"begin:"<<i<<"\tend:"<<j<<"\tweight:"<<arc[i][j]<<endl; } } }
void Graph::print_arc(){ for(int i=0;i<vertex_num;i++){ for(int j=0;j<vertex_num;j++){ cout<<arc[i][j]<<"\t"; } cout<<endl; } } void Graph::Dijkstra(int begin){ vector<int> result(vertex_num,INT_MAX); result[begin]=0; vector<int> distance(vertex_num,INT_MAX); for(int i=0;i<vertex_num;i++){ distance[i]=arc[begin][i]; } for(int k=0;k<vertex_num-1;k++){ int min_distance=INT_MAX; int min_index=0; for(int i=0;i<vertex_num;i++){ if(distance[i]!=0 && distance[i]<min_distance){ min_distance=distance[i]; min_index=i; } } cout<<min_index<<endl; result[min_index]=min_distance; distance[min_index]=0;
for(int i=0;i<vertex_num;i++){ if(distance[i]!=0 && arc[min_index][i]<INT_MAX){ distance[i]=min(distance[i],min_distance+arc[min_index][i]); } } }
for(int i=0;i<vertex_num;i++){ cout<<"end:"<<i<<"\tweight:"<<result[i]<<endl; }
}
|