C++代码,数据结构-最短路径(两种情况)(迪杰斯特拉算法和弗洛伊德算法)
来源:互联网 发布:锐思数据库 编辑:程序博客网 时间:2024/05/01 08:12
1.单源的,从有向图某个源点, 到其他点的最短路径
利用算法迪杰斯特拉算法;
Dijkstra算法的基本思想:
一个辅助数组D[max_v];每个D[i]表示当前所知源点到vi的最短路径的长度
一个辅助集合S,记录已找到最短路径的顶点的集合,他是逐步补充的;知道S集合包括所有点,起初S集合包含源点
1.先找出源点直接可达到顶点i,并把权记录到D[i]中,不可达到顶点记为最大值;
2.然后进行n-1次循环,把其他点一次找出最短路径;
每次循环先找出D中最小的值min,和v(D[v]=min); 把v加入到集合S中,
3.然后寻找不属于S集合的点w,如果min+dut(v-w的权值)<D[w],则更新D[w]的值,
4.重复2,和3,知道S集合包括所有点。
下面是代码,我自己又写了一个函数来呈现结果,
#include<iostream>#include<fstream>#define Max_v 200using namespace std;//算法7.15 最短路径struct Arccell{int adj;};typedef Arccell adjmatric[Max_v][Max_v];struct Mgraph{char vexs[Max_v]; //顶点向量adjmatric arcs; //邻接矩阵int vexnum,arcnum; //顶点数 和 弧数};int locate(Mgraph G,char ch){for(int i=0;i!=G.vexnum;++i){ if(G.vexs[i]==ch)return i;}}void createDG(Mgraph &G){//采用数组表示法,构造有向图 cout<<"Please enter the vexnum and arcnum of the G graph"<<endl; cin>>G.vexnum>>G.arcnum; cout<<"Please enter the dians of G"<<endl; for(int i=0;i!=G.vexnum;++i){cin>>G.vexs[i];}//构造顶点向量 for(int i=0;i!=G.vexnum;++i){//初始化矩阵 for(int j=0;j!=G.vexnum;++j){ G.arcs[i][j].adj=10000; } }char v1,v2;int w;cout<<"Please enter "<<G.arcnum<<" arcnums"<<endl;for(int k=0;k!=G.arcnum;++k){ cin>>v1>>v2>>w; int i=locate(G,v1); int j=locate(G,v2); G.arcs[i][j].adj=w;}}void printgraph(Mgraph M){cout<<"\n"<<"The graph has "<<M.vexnum<<"vertex and "<<M.arcnum<<"arc"<<endl;cout<<"The vertex is:"; for(int i=0;i!=M.vexnum;++i){cout<<M.vexs[i]<<" ";}cout<<endl; for(int i=0;i!=M.vexnum;++i){ for(int j=0;j!=M.vexnum;++j){ if(M.arcs[i][j].adj!=10000) cout<<M.vexs[i]<<" "<<M.vexs[j]<<endl; } } for(int i=0;i!=M.vexnum;++i){ for(int j=0;j!=M.vexnum;++j){ cout<<M.arcs[i][j].adj<<" "; }cout<<endl; }}//单源,某顶点到各顶点的最短路径void Shortestpath(Mgraph G,int v0,int ppp[][Max_v],int*D){ for(int i=0;i!=Max_v;++i){ //初始化pathbool for(int j=0;j!=Max_v;++j){ ppp[i][j]=false;}} bool finals[Max_v];//如果finals[v]为true,则已经求得v0到v的最短路径了 for(int v=0;v!=G.vexnum;++v){ finals[v]=false; D[v]=G.arcs[v0][v].adj; //初始化 for(int w=0;w!=G.vexnum;++w){ ppp[v][w]=false;}//设置空路径 if(D[v]<10000){ppp[v][v0]=true; ppp[v][v]=true;}//目前找到的最短的路径 } D[v0]=0;finals[v0]=true;//v0属于s集 int v; //开始主循环,每次求得v0到某个v顶点的最短路径,并加到s集中 for(int i=1;i!=G.vexnum;++i){//其余G.vexnum-1个顶点 int mins=10000; for(int w=0;w!=G.vexnum;++w){//当前已知离v0最近的点,并把其加到s集中。随后更新已知到顶点的最短长度 if(!finals[w]&&D[w]<mins){ v=w;mins=D[w];} }finals[v]=true; for(int w=0;w!=G.vexnum;++w){ if(!finals[w]&&(mins+G.arcs[v][w].adj<D[w])){//w不在s集,更新最短距离 D[w]=mins+G.arcs[v][w].adj; for(int i=0;i!=Max_v;++i){ ppp[w][i]=ppp[v][i]; } ppp[w][w]=true; } } }//for}bool yes(Mgraph G,int tem,int j){if(G.arcs[tem][j].adj!=10000)return true;else return false;}//打印结果void printresult(Mgraph G,int v0,int ppp[][Max_v],int*D){for(int i=0;i!=G.vexnum;++i){ if(i!=v0){ if(D[i]==10000)cout<<" "<<G.vexs[v0]<<"-->>"<<G.vexs[i]<<" 无路径,不可达"<<endl;//路径长度等于最大值,则不可达else{ cout<<" "<<G.vexs[v0]<<"-->>"<<G.vexs[i]<<" 长度:"<<"="<<" "<<D[i]<<" 路径:"<<G.vexs[v0]<<" "; int tem=v0; for(int j=0;j!=G.vexnum;++j){//根据数组pathbool来找到路径 if(ppp[i][j]==1&&j!=v0&&j!=i&&yes(G,tem,j)){ cout<<G.vexs[j]<<" " ; ppp[i][j]=0;tem=j;j=0; } }cout<<G.vexs[i]<<endl;} }}}int main(){ifstream infile("rebuf.txt");streambuf* backup=cin.rdbuf();//记录原状态cin.rdbuf(infile.rdbuf()); Mgraph m; createDG(m);printgraph(m);cout<<endl;int pathbool[Max_v][Max_v];//记录路径,如果pathbool[v][w]为true。则w是v0到v最短路径上的顶点int D[Max_v];//记录当前所找到的从始点到每个终点vi的最短路径的长度Shortestpath(m,0,pathbool,D);//迪杰斯特拉算法,算法7.15cout<<endl;printresult(m,0,pathbool,D);//打印结果cout<<endl;cin.rdbuf(backup);//解绑重定向//利用迪杰斯特拉算法来求一对顶点之间的最短路径cout<<"请输入起点";char x,y;cin>>x;Shortestpath(m,locate(m,x),pathbool,D);cout<<"请输入终点";cin>>y;int iy=locate(m,y);if(D[iy]==10000)cout<<"不可达"<<endl;else{ cout<<" "<<m.vexs[locate(m,x)]<<"-->>"<<m.vexs[iy]<<" 长度:"<<"="<<" "<<D[iy]<<" 路径:"<<m.vexs[locate(m,x)]<<" "; int tem=locate(m,x); int i=iy; for(int j=0;j!=m.vexnum;++j){//根据数组pathbool来找到路径 if(pathbool[i][j]==1&&j!=locate(m,x)&&j!=i&&yes(m,tem,j)){//类似上面打印结果,这次只需打印一个路径 cout<<m.vexs[j]<<" " ; pathbool[i][j]=0;tem=j;j=0; } }cout<<m.vexs[i]<<endl;} return 0;}
rebuf.txt:
6 8
a b c d e f
a c 10
a e 30
a f 100
b c 5
c d 50
d f 10
e d 20
e f 60
运行结果:
2.每一对顶点之间的最短路径
首先可以利用迪杰斯特拉算法来解决,上面最后已经给出了方法。
下面使用弗洛伊德算法,时间复杂度相同,但是形式上更加简洁。
过了一个春节,有好几天没动,真是罪过,今天总算把艰苦的第七章给结束了,Floyd算法。
直接上代码:
#include<iostream>#include<fstream>#define Max_v 200using namespace std;//算法7.16 最短路径,Floyd算法struct Arccell{int adj;};typedef Arccell adjmatric[Max_v][Max_v];struct Mgraph{char vexs[Max_v]; //顶点向量adjmatric arcs; //邻接矩阵int vexnum,arcnum; //顶点数 和 弧数};int locate(Mgraph G,char ch){for(int i=0;i!=G.vexnum;++i){ if(G.vexs[i]==ch)return i;}}void createDG(Mgraph &G){//采用数组表示法,构造有向图 cout<<"Please enter the vexnum and arcnum of the G graph"<<endl; cin>>G.vexnum>>G.arcnum; cout<<"Please enter the dians of G"<<endl; for(int i=0;i!=G.vexnum;++i){cin>>G.vexs[i];}//构造顶点向量 for(int i=0;i!=G.vexnum;++i){//初始化矩阵 for(int j=0;j!=G.vexnum;++j){ if(i==j)G.arcs[i][j].adj=0; else G.arcs[i][j].adj=10000; } }char v1,v2;int w;cout<<"Please enter "<<G.arcnum<<" arcnums"<<endl;for(int k=0;k!=G.arcnum;++k){ cin>>v1>>v2>>w; int i=locate(G,v1); int j=locate(G,v2); G.arcs[i][j].adj=w;}}void printgraph(Mgraph M){cout<<"\n"<<"The graph has "<<M.vexnum<<"vertex and "<<M.arcnum<<"arc"<<endl;cout<<"The vertex is:"; for(int i=0;i!=M.vexnum;++i){cout<<M.vexs[i]<<" ";}cout<<endl; for(int i=0;i!=M.vexnum;++i){ for(int j=0;j!=M.vexnum;++j){ if(M.arcs[i][j].adj!=10000) cout<<M.vexs[i]<<" "<<M.vexs[j]<<endl; } } for(int i=0;i!=M.vexnum;++i){ for(int j=0;j!=M.vexnum;++j){ cout<<M.arcs[i][j].adj<<" "; }cout<<endl; }}bool yes(Mgraph G,int tem,int j){if(G.arcs[tem][j].adj!=10000)return true;else return false;}//算法7.16void Short_path_floyd(Mgraph G,int p[3][3][3],int D[3][3]){//若p[v][w][u]为true,则U为v到w当前求得最短路径上的顶点for(int v=0;v!=G.vexnum;++v){ for(int w=0;w!=G.vexnum;++w){D[v][w]=G.arcs[v][w].adj;for(int u=0;u!=G.vexnum;++u){p[v][w][u]=false;}if(D[v][w]<10000){//从v到w有直接路径,设置p p[v][w][v]=true; p[v][w][w]=true;}}}for(int u=0;u!=G.vexnum;++u){//最主要过程,不断的用u作为中间点,寻找最短路径 for(int v=0;v!=G.vexnum;++v){ for(int w=0;w!=G.vexnum;++w){ if(D[v][u]+D[u][w]<D[v][w]){ D[v][w]=D[v][u]+D[u][w]; for(int i=0;i!=G.vexnum;++i){ p[v][w][i]=p[v][u][i];}//v到u上的点也是v到w上的点 } }}}}int main(){ifstream infile("rebuf.txt");streambuf* backup=cin.rdbuf();//记录原状态cin.rdbuf(infile.rdbuf()); Mgraph m; createDG(m);printgraph(m);cout<<endl;int p[3][3][3];//p[v][w][u]=true,则表示u为当前求得最短路径上的顶点,p起到记录到作用int d[3][3];//实时跟新v到w的最短路径长度Short_path_floyd(m,p,d);cin.rdbuf(backup);cout<<"请输入起点";char x,y;cin>>x;int ix=locate(m,x);cout<<"请输入终点";cin>>y;int iy=locate(m,y); cout<<" "<<m.vexs[ix]<<"-->>"<<m.vexs[iy]<<" 长度:"<<"="<<" "<<d[ix][iy]<<" 路径:"<<m.vexs[ix]<<" ";p[ix][iy][ix]=0;p[ix][iy][iy]=0;int tem=ix;for(int i=0;i!=m.vexnum;++i){ if(p[ix][iy][i]==1&&yes(m,tem,i)){cout<<m.vexs[i]<<" ";p[ix][iy][i]=0; tem=i; i=0;}} cout<<m.vexs[iy]<<endl; return 0;}
rebuf.txt:3 5
a b c
a b 5
a c 11
b a 6
b c 2
c a 3
书上图7.36
运行结果:
0 0
- C++代码,数据结构-最短路径(两种情况)(迪杰斯特拉算法和弗洛伊德算法)
- 最短路径--弗洛伊德(Floyd)算法
- 最短路径(弗洛伊德算法)
- 数据结构之---C语言实现最短路径之Floyd(弗洛伊德)算法
- 图(最短路径算法————迪杰斯特拉算法和弗洛伊德算法)
- 图之最短路径算法-Dijkstra(迪杰斯特拉)算法和Floyd(弗洛伊德)算法
- 算法:最短路径之弗洛伊德(Floyd)算法
- 最短路径算法(3)—Floyd(弗洛伊德)算法
- 弗洛伊德最短路径算法
- 弗洛伊德算法--最短路径
- 最短路径-弗洛伊德算法
- 弗洛伊德最短路径算法
- 最短路径(弗洛伊德算法)
- 最短路径--弗洛伊德算法
- 最短路径:弗洛伊德算法
- 弗洛伊德最短路径算法
- 弗洛伊德最短路径算法
- 最短路径---弗洛伊德算法
- CentOs 安装gcc 4.8.1
- UVA 11461 - Square Numbers 数学水题
- C++学习日记4 C++常量和算术表达式
- 罗大柚OpenGL ES教程系列LessonOne(Part 1): 绘制一个三角形
- 函数和数组
- C++代码,数据结构-最短路径(两种情况)(迪杰斯特拉算法和弗洛伊德算法)
- 枪枪中枪
- 84. 在状态中思考
- 获取Java的32位MD5实现
- 不算退役贴的退役贴
- 2014年读书计划
- poj 2897
- 游戏引擎开发之路
- 软件开发工程师常用的工具软件