|
功能是按给出的一张含有路径长度地图,从地图中所有路径中找出任意两个城市间的最短路径,算出最短路径的长度及其途经的城市。
使用邻接矩阵作为图的结构,使用队列记录最短路径上途经的城市,使用迪杰斯特拉(Dijkstra)算法,详细说明请见代码中注释。
分为有向图和无向图两部分 有向图是指每条路径都是有方向的,只能按图中固定的方向走。 无向图是指每条路径都是双向的,就像正常的公路。 R>源程序及可执行程序
file: Click to Download
地图如下:

程序结果,以郑州为起点,列出其到各个城市的最短路径。

列出各个城市间的距离表,分别为有向图和无向图的邻接矩阵。


代码部分: 队列结构:
#include<iostream.h>
// 定义 状态代码 及 数据类型 #define NULL 0 #define OK 1 #define ERROR 0 #define INFINITY 255 #define MAX_VERTEX_NUM 20
typedef int Status; typedef int ElemType;
// ----------------------- 队列结构 -------------------------
// 节点存储结构 typedef struct QNode{ ElemType data; struct QNode *next; }QNode,*QueuePtr;
// 队列 typedef struct{ QueuePtr front; QueuePtr rear; }LinkQueue;
// 初始化队列 Status InitQueue(LinkQueue &Q){ Q.front=Q.rear=new QNode; if(!Q.front) return ERROR; Q.front->next=NULL; return OK; }
// 入队 Status EnQueue(LinkQueue &Q,ElemType e){ QueuePtr p=NULL; p=new QNode; if(!p) return ERROR; p->data=e; p->next=NULL; Q.rear->next=p; Q.rear=p; return OK; }
// 出队 Status DeQueue(LinkQueue &Q,ElemType &e){ QueuePtr p=NULL; if(Q.front==Q.rear) return ERROR; p=Q.front->next; e=p->data; Q.front->next=p->next; if(Q.rear==p) // 注意当出队后为空队的情况 Q.rear=Q.front; delete p; return OK; }
// 判断是否为空队列 Status EmptyQueue(LinkQueue &Q){ return Q.front==Q.rear?true:false; }
// 复制队列(copy Q1 to Q2) Status CopyQueue(LinkQueue &Q1,LinkQueue &Q2){ int e; QueuePtr p; while(!EmptyQueue(Q2)){ // clean Q2 DeQueue(Q2,e); } // copy one by one p=Q1.front->next; while(p){ e=p->data; p=p->next; EnQueue(Q2,e); } return OK; }
图的结构-邻接矩阵
// ---------------------- 图的结构:邻接矩阵 --------------------------//
// 邻接矩阵元素 typedef struct ArcCell{ int adj; // arc value: >0, INFINITY: no link char *info; }AcrCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
// 图的结构 typedef struct{ char vexs[MAX_VERTEX_NUM][5]; // 顶点数组 AdjMatrix arcs; // 邻接矩阵 int vexnum; // 图当前的顶点数 int arcnum; // 图当前边的个数 }MGraph;
// 建立邻接图(key=1为有向网,key=0为无向网) Status createUDN(MGraph &G,int vexnum,int edgenum,char *names,char *edges,int key){ int i,j,k,value; // 输入当前图的顶点数,边个数 G.vexnum=vexnum; G.arcnum=edgenum; // 各个顶点数据 for(i=0;i<G.vexnum;++i){ for(j=0;j<4;j++){ G.vexs[i][j]=*names; names++; } G.vexs[i][4]='\0'; } // 初始化邻接矩阵(全为INFINITY) for(i=0;i<MAX_VERTEX_NUM;++i){ for(j=0;j<MAX_VERTEX_NUM;++j){ G.arcs[i][j].adj=INFINITY; G.arcs[i][j].info=NULL; } } // 建立邻接矩阵每条边的数值 for(k=0;k<G.arcnum;++k){ i=int(*edges)-48; edges++; j=int(*edges)-48; edges++; value=(int(*edges)-48)*10; edges++; value+=int(*edges)-48; edges++; G.arcs[i][j].adj=value; if(!key){ G.arcs[j][i].adj=value; } } return OK; }
// 打印出邻接矩阵 void PrintGraph(MGraph &G){ int i,j; cout<<"\n//--------------- PrintMatrix -----------------//\n\n "; for(i=0;i<G.vexnum;++i){ cout<<G.vexs[i]<<" "; } cout<<endl; for(i=0;i<G.vexnum;++i){ cout<<"\n\n"<<G.vexs[i]<<" "; for(j=0;j<G.vexnum;++j){ if(G.arcs[i][j].adj==INFINITY) cout<<" / "; else cout<<" "<<G.arcs[i][j].adj<<" "; } } cout<<"\n\n//--------------- PrintMatrix -----------------//\n\n\n\n"; }
求最短路径程序
// ---------------------- 求源点v0到各点的最短路径 --------------------------//
void ShortestPath(MGraph &G,int v0){ int D[MAX_VERTEX_NUM],final[MAX_VERTEX_NUM],i,w,v=0,min; // 建立队列数组,用以依次储存最短的路径 LinkQueue Q[MAX_VERTEX_NUM]; // 初始化数组 for(i=0;i<G.vexnum;++i){ InitQueue(Q[i]); D[i]=G.arcs[v0][i].adj; final[i]=false; } final[v0]=true; // 一个一个循环找出最短距离(共vexnum-1个) for(i=1;i<G.vexnum;++i){ min=INFINITY; // 扫描找出非final集中最小的D[] for(w=0;w<G.vexnum;++w){ if(!final[w] && D[w]<min){ v=w; min=D[w]; } } final[v]=true; // 更新各D[]数据 for(w=0;w<G.vexnum;++w){ if(!final[w] && G.arcs[v][w].adj+min<D[w]){ D[w]=G.arcs[v][w].adj+min; CopyQueue(Q[v],Q[w]); EnQueue(Q[w],v); } } } // 打印出结果 cout<<"//--------------- ShortestPath -----------------//\n\n"; cout<<" 出发地->目的地\t最短距离\t详细路径\n\n"; for(i=0;i<G.vexnum;i++){ if(D[i]!=INFINITY){ cout<<" "<<G.vexs[v0]<<" -> "<<G.vexs[i]<<"\t\t"<<D[i]<<" \t\t"; cout<<G.vexs[v0]; while(!EmptyQueue(Q[i])){ DeQueue(Q[i],v); cout<<" -> "<<G.vexs[v]; } cout<<" -> "<<G.vexs[i]<<endl; }else{ cout<<" "<<G.vexs[v0]<<" -> "<<G.vexs[i]<<"\t\tNo path!\n"; } } cout<<"\n//--------------- ShortestPath -----------------//\n\n\n"; }
主程序
void PrintCity(char *names,int vexnum){ int i,j; cout<<"城市列表:\n\n"; for(i=0;i<vexnum;++i){ cout<<" "<<i<<"-"; for(j=0;j<4;j++){ cout<<*names; names++; } cout<<" "; } cout<<"\n请选择出发城市 >"; }
void main(){ MGraph G;
// 图的结构数据 char *edges,*names; int vexnum,arcnum,city,kind; vexnum=10; arcnum=14; names="郑州北京天津南昌上海贵阳株洲广州兰州西宁"; edges="01450235035012201591187024503450585056205750604063409835";
// 用户界面 do{ PrintCity(names,vexnum); cin>>city; cout<<"\n\n操作:\n0-无向图列表 1-有向图列表\n2-无向图矩阵 3-有向图矩阵\n4-选择城市 5-退出\n\n请选择操作 >"; do{ cin>>kind; if(kind>=0 && kind <=3){ createUDN(G,vexnum,arcnum,names,edges,kind%2); switch(kind/2){ case 0:ShortestPath(G,city); break; case 1:PrintGraph(G); break; } } cout<<"\n\n操作:\n0-无向图列表 1-有向图列表\n2-无向图矩阵 3-有向图矩阵\n4-选择城市 5-退出\n\n请选择操作 >"; } while(kind<4); } while(kind<5); }
|