实习三 求最短路径Word格式文档下载.docx
《实习三 求最短路径Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《实习三 求最短路径Word格式文档下载.docx(12页珍藏版)》请在冰豆网上搜索。
具体思想
如下所示的有向图
跟据如上图所示的有向图,建立如下图所示的邻接表存储结构,数组的data域存储图的顶点信息,source域存储该顶点在数组下标,这个下标也是所有以该顶点为狐尾的边在数组中的下标,adj域为该顶点的邻接顶点单链表的头指针。
其中结点结构体定义如下:
typedefstructNode{
intdest;
//连接表的弧头顶点序号
intweight;
structNode*next;
//单链表的下一个结点指针
}Edge;
//邻接边单链表的结点结构体
typedefstruct{
DataTypedata;
//顶点数据元素
intsource;
//邻接边的狐尾顶点序号
Edge*adj;
//邻接边的头指针
}AdjLHeight;
typedefstruct{
AdjLHeighta[MaxVertices];
//邻接表数组
intnumOfVerts;
//顶点个数
intnumOfEdges;
//边个数
}AdjLGraph;
//连接表结构体
introw;
//行下标
intcol;
//列下标
//权值
}RowCol;
//边信息结构体
用邻接表构建图完成后,Dijkstra算法求最短路径如下:
voidDijkstra(AdjLGraph*G,intv0,intdistance[],intpath[])
{//带权图G从下标v0顶点到其他顶点的最短距离distance和最短路径下标path
intn=G->
numOfVerts;
int*s=(int*)malloc(sizeof(int)*n);
intminDis,i,j,u;
Edge*p,*q;
p=G->
a[v0].adj;
while(p!
=NULL)
{//顶点能一次到达的,路径长度为其权值
i=p->
dest;
distance[i]=p->
weight;
path[i]=v0;
p=p->
next;
}
for(i=0;
i<
n;
i++)
{//顶点一次不能到达的,路径长度为MaxWeight
s[i]=0;
if(path[i]!
=v0)
{
path[i]=-1;
distance[i]=MaxWeight;
s[v0]=1;
//将序号v0包含在集合s内
distance[v0]=0;
//顶点自己到自己的路径为0
{
minDis=MaxWeight;
for(j=0;
j<
j++)
if(s[j]==0&
&
distance[j]<
minDis)
u=j;
minDis=distance[j];
if(minDis==MaxWeight)return;
s[u]=1;
//将选出的终点序号u并入S集合中
q=G->
a[u].adj;
//从第a[u]个点开始
while(q!
if(s[q->
dest]==0&
q->
weight<
MaxWeight&
distance[u]+q->
weight<
distance[q->
dest])
{//若顶点通过几次到该点的和的权值小于一次到该点的权值,则修改其到该点的权值
distance[q->
dest]=distance[u]+q->
path[q->
dest]=u;
q=q->
}
3.调试分析
首先以邻接表作为图的存储结构,其中邻接表创建图函数课本上已经给出,实现起来比较简单,重要的是Dijkastra算法求最短路径。
其时间复杂度为T(
)。
首先用充分了解Dijkastra算法思想,其中距离标号uj:
记录的是从起点到该节点的最短路长度的上界。
前趋标号pred(j):
当取到uj时,节点j前面的那个直接前趋(标号)。
算法通过不断改变这些标号进行秩代计算。
算法结束时,距离标号表示起点到节点的最短路长度。
前趋标号记录着最短路路径。
调试过程中顶点到其本身为所设定的最大值而不是零,调试发现设置一个distance[v0]=0,便可以解决该问题。
开始时v0在集合S中,然后在所有的不在S集合中的顶点之中,选取distance[i]为最小的一个,设为u;
将选出的终点序号u并入S集合中。
4.用户手册
在VC++6.0中运行该程序后,便可通过Dijkstra算法求出顶点(本程序选取的顶点为1)到其他点的最短路径。
5.测试结果
6.源代码
………………………………………………………Dijkastra.h………………………………..
voidAdjInitiate(AdjLGraph*G)
{//初始化图G
inti;
G->
numOfEdges=0;
numOfVerts=0;
MaxVertices;
i++){
a[i].source=i;
//置邻接边的弧头顶点序号
a[i].adj=NULL;
}
voidInsertVertex(AdjLGraph*G,inti,DataTypevertex)
{//在图G中的第i(0<
=i<
MaxVertices)个位置插入顶点元数据元素vertex
if(i>
=0&
i<
MaxVertices){
a[i].data=vertex;
//存储顶点数据元素vertex
numOfVerts++;
//个数加1
elseprintf("
顶点越界"
);
voidInsertEdge(AdjLGraph*G,intv1,intv2,intweight)
{//在图G中加入边<
v1,v2>
Edge*p;
if(v1<
0||v1>
=G->
numOfVerts||v2<
0||v2>
numOfVerts){
printf("
参数v1或v2越界出错!
"
return;
p=(Edge*)malloc(sizeof(Edge));
//申请邻接边单链表结点空间
p->
dest=v2;
//置邻接边弧头序号
weight=weight;
next=G->
a[v1].adj;
//新结点插入单链表的表头
a[v1].adj=p;
//头指针指向新的单链表表头
numOfEdges++;
//边个数加1
voidDeleteEdge(AdjLGraph*G,intv1,intv2)
{//删除图G中的边<
Edge*curr,*pre;
0||v2>
pre=NULL;
curr=G->
while(curr!
=NULL&
curr->
dest!
=v2)
{//在v1顶点的邻接边单链表中查找v2顶点
pre=curr;
curr=curr->
}//删除邻接边<
if(curr!
=NULL&
dest==v2&
pre==NULL)
{//当邻接边<
的结点是单链表的第一个结点时
a[v1].adj=curr->
free(curr);
numOfEdges--;
elseif(curr!
dest==v2&
pre!
的结点不是单链表的第一个结点时
pre->
next=curr->
边<
不存在!
//当邻接边<
不存在时
voidAdjDestroy(AdjLGraph*G)
{//撤销图G中的所有单链表占用的存储空间
i<
a[i].adj;
=NULL){
q=p->
free(p);
p=q;
voidCreatGraph(AdjLGraph*G,DataTypev[],intn,RowCold[],inte)
{//创建有n个顶点e条边的图G
//顶点信息存放在数组v中,边信息存放在数组d中
inti,k;
AdjInitiate(G);
//初始化
i++)InsertVertex(G,i,v[i]);
//插入顶点
for(k=0;
k<
e;
k++)
InsertEdge(G,d[k].row,d[k].col,d[k].weight);
//插入边
voidDijkstra(AdjLGraph*G,intv0,intdistance[],intpath[])
………………………………………………………main.cpp……………………………………
#include<
stdio.h>
#defineMaxVertices10
#defineMaxWeight10000
malloc.h>
typedefintDataType;
#include"
Dijkastra.h"
voidmain(){
AdjLGraphG;
DataTypea[]={1,2,3,4,5,6};
RowCold[]={{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}};
intdistance[6],path[6];
inti,n=6,e=10;
CreatGraph(&
G,a,n,d,e);
Dijkstra(&
G,0,distance,path);
用Dijkstra算法求得从顶点%d到其他各顶点的最短距离为:
\n"
G.a[0].data);
到顶点%d的最短距离为%d\n"
G.a[i].data,distance[i]);