1、实习三 求最短路径实习三1.需求分析:【问题描述】:设计一个算法,求图中一个源点到其他各顶点的最短路径。【基本要求】:(1)以邻接表作为存储结构。(2)用Dijkstra算法求最短路径。(3)按长度非递减次序打印输出最短路径的长度及相应路径。【开发环境】:系统:windows7编程软件:VC+6.02.设计:邻接表是一种链式存储结构。在邻接表中,对图中每个顶点建立一个单链表,第i个单链表中的结点表示依附于顶点Vi的边(对有向图是以顶点Vi为尾的弧)。每个结点由3个域组成,其中邻接点域(dest)指示与顶点Vi邻接的点在图中的位置,链域(next)指示下一条边或弧的结点;数据域(weight)存
2、储和边或弧相关的信息,如权值等。所以一开始必须先定义邻接表的边结点类型以及邻接表类型,并对邻接表进行初始化,然后根据所输入的相关信息,包括图的顶点数、边数、是否为有向,以及各条边的起点与终点序号,建立图的邻接表。图的邻接表建立后,利用狄克斯特拉算法求出最短路径。狄克斯特拉算法的思想:设置两个顶点的集合S和T,集合S中存放已找到最短路径的顶点,集合T中存放当前还未找到最短路径的顶点。初始状态时,集合S中只包含源点,设为,然后从集合T中选择到源点路径长度最短的顶点u加入到集合S中,集合S中每加入一个新的顶点u,都要修改源点到集合T中剩余顶点的当前最短路径长度值,集合T中各顶点的新的当前最短路径长度
3、值为原来的当前最短路径长度值与从源点过顶点u到达该顶点的路径长度中的较小者。此过程不断重复,直到集合T中的顶点全部加入到集合S中为止。具体思想 如下所示的有向图 跟据如上图所示的有向图,建立如下图所示的邻接表存储结构,数组的data域存储图的顶点信息,source域存储该顶点在数组下标,这个下标也是所有以该顶点为狐尾的边在数组中的下标,adj域为该顶点的邻接顶点单链表的头指针。其中结点结构体定义如下:typedef struct Node int dest;/连接表的弧头顶点序号 int weight; struct Node *next;/单链表的下一个结点指针Edge;/邻接边单链表的结点
4、结构体typedef struct DataType data;/顶点数据元素 int source;/邻接边的狐尾顶点序号 Edge *adj;/邻接边的头指针AdjLHeight;typedef struct AdjLHeight aMaxVertices;/邻接表数组 int numOfVerts;/顶点个数 int numOfEdges;/边个数AdjLGraph;/连接表结构体typedef struct int row;/行下标 int col;/列下标 int weight;/权值RowCol;/边信息结构体用邻接表构建图完成后,Dijkstra算法求最短路径如下: void D
5、ijkstra(AdjLGraph *G,int v0,int distance,int path)/带权图G从下标v0顶点到其他顶点的最短距离distance和最短路径下标path int n=G-numOfVerts;/顶点个数 int *s=(int *)malloc(sizeof(int)*n); int minDis,i,j,u; Edge *p,*q; p=G-av0.adj; while(p!=NULL) /顶点能一次到达的,路径长度为其权值 i=p-dest; distancei=p-weight; pathi=v0; p=p-next; for(i=0;in;i+) /顶点一
6、次不能到达的,路径长度为MaxWeight si=0; if(pathi!=v0) pathi=-1; distancei=MaxWeight; sv0=1;/将序号v0包含在集合s内 distancev0=0;/顶点自己到自己的路径为0 for(i=0;in;i+) minDis=MaxWeight; for(j=0;jn;j+) if(sj=0 & distancejau.adj;/从第au个点开始 while(q!=NULL) if(sq-dest=0 & q-weight weightdest) /若顶点通过几次到该点的和的权值小于一次到该点的权值,则修改其到该点的权值 distanc
7、eq-dest=distanceu+q-weight; pathq-dest=u; q=q-next; 3.调试分析 首先以邻接表作为图的存储结构,其中邻接表创建图函数课本上已经给出,实现起来比较简单,重要的是Dijkastra算法求最短路径。其时间复杂度为T()。首先用充分了解Dijkastra算法思想,其中距离标号uj:记录的是从起点到该节点的最短路长度的上界。前趋标号pred(j):当取到uj时,节点j前面的那个直接前趋(标号)。算法通过不断改变这些标号进行秩代计算。算法结束时,距离标号表示起点到节点的最短路长度。前趋标号记录着最短路路径。调试过程中顶点到其本身为所设定的最大值而不是零,
8、调试发现设置一个distancev0=0,便可以解决该问题。开始时v0在集合S中,然后在所有的不在S集合中的顶点之中,选取distancei为最小的一个,设为u;将选出的终点序号u并入S集合中。4.用户手册 在VC+6.0中运行该程序后,便可通过Dijkstra算法求出顶点(本程序选取的顶点为1)到其他点的最短路径。5.测试结果 6.源代码Dijkastra.h.typedef struct Node int dest;/连接表的弧头顶点序号 int weight; struct Node *next;/单链表的下一个结点指针Edge;/邻接边单链表的结点结构体typedef struct D
9、ataType data;/顶点数据元素 int source;/邻接边的狐尾顶点序号 Edge *adj;/邻接边的头指针AdjLHeight;typedef struct AdjLHeight aMaxVertices;/邻接表数组 int numOfVerts;/顶点个数 int numOfEdges;/边个数AdjLGraph;/连接表结构体typedef struct int row;/行下标 int col;/列下标 int weight;/权值RowCol;/边信息结构体void AdjInitiate(AdjLGraph *G)/初始化图G int i; G-numOfEdge
10、s=0; G-numOfVerts=0; for(i=0;iai.source=i;/置邻接边的弧头顶点序号 G-ai.adj=NULL; void InsertVertex(AdjLGraph *G,int i,DataType vertex)/在图G中的第i(0=i=0 & iai.data=vertex;/存储顶点数据元素vertex G-numOfVerts+;/个数加1 else printf(顶点越界);void InsertEdge(AdjLGraph *G,int v1,int v2,int weight)/在图G中加入边 Edge *p; if(v1=G-numOfVerts
11、 | v2=G-numOfVerts) printf(参数v1或v2越界出错!); return; p=(Edge *)malloc(sizeof(Edge);/申请邻接边单链表结点空间 p-dest=v2;/置邻接边弧头序号 p-weight=weight; p-next=G-av1.adj;/新结点插入单链表的表头 G-av1.adj=p;/头指针指向新的单链表表头 G-numOfEdges+;/边个数加1void DeleteEdge(AdjLGraph *G,int v1,int v2)/删除图G中的边 Edge *curr,*pre; if(v1=G-numOfVerts | v2=
12、G-numOfVerts) printf(参数v1或v2越界出错!); return; pre=NULL; curr=G-av1.adj; while(curr!=NULL & curr-dest != v2) /在v1顶点的邻接边单链表中查找v2顶点 pre=curr; curr=curr-next; /删除邻接边 if(curr != NULL & curr-dest = v2 & pre=NULL) /当邻接边的结点是单链表的第一个结点时 G-av1.adj=curr-next; free(curr); G-numOfEdges-; else if(curr != NULL & curr
13、-dest=v2 & pre!=NULL) /当邻接边的结点不是单链表的第一个结点时 pre-next=curr-next; free(curr); G-numOfEdges-; else printf(边不存在!);/当邻接边不存在时 void AdjDestroy(AdjLGraph *G)/撤销图G中的所有单链表占用的存储空间 int i; Edge *p,*q; for(i=0;i numOfVerts;i+) p=G-ai.adj; while(p!=NULL) q=p-next; free(p); p=q; void CreatGraph(AdjLGraph *G ,DataTyp
14、e v,int n,RowCol d,int e)/创建有n个顶点e条边的图G/顶点信息存放在数组v中,边信息存放在数组d中 int i,k; AdjInitiate(G);/初始化 for(i=0;in;i+) InsertVertex(G,i,vi);/插入顶点 for(k=0;knumOfVerts;/顶点个数 int *s=(int *)malloc(sizeof(int)*n); int minDis,i,j,u; Edge *p,*q; p=G-av0.adj; while(p!=NULL) /顶点能一次到达的,路径长度为其权值 i=p-dest; distancei=p-weig
15、ht; pathi=v0; p=p-next; for(i=0;in;i+) /顶点一次不能到达的,路径长度为MaxWeight si=0; if(pathi!=v0) pathi=-1; distancei=MaxWeight; sv0=1;/将序号v0包含在集合s内 distancev0=0;/顶点自己到自己的路径为0 for(i=0;in;i+) minDis=MaxWeight; for(j=0;jn;j+) if(sj=0 & distancejau.adj;/从第au个点开始 while(q!=NULL) if(sq-dest=0 & q-weight weightdest) /若
16、顶点通过几次到该点的和的权值小于一次到该点的权值,则修改其到该点的权值 distanceq-dest=distanceu+q-weight; pathq-dest=u; q=q-next; main.cpp#include#define MaxVertices 10#define MaxWeight 10000 #includetypedef int DataType;#includeDijkastra.hvoid main() AdjLGraph G; DataType a=1,2,3,4,5,6; RowCol d=0,1,20,0,2,15,1,0,2,1,4,10,1,5,30,2,1,4,2,5,10,4,3,15,5,3,4,5,4,10; int distance6,path6; int i,n=6,e=10; CreatGraph(&G,a,n,d,e); Dijkstra(&G,0,distance,path); printf(用Dijkstra算法求得从顶点%d到其他各顶点的最短距离为:n,G.a0.data); for(i=0;in;i+) printf(到顶点%d的最短距离为%dn,G.ai.data,distancei);
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1