数据结构上机报告 狄克斯特拉.docx
《数据结构上机报告 狄克斯特拉.docx》由会员分享,可在线阅读,更多相关《数据结构上机报告 狄克斯特拉.docx(14页珍藏版)》请在冰豆网上搜索。
数据结构上机报告狄克斯特拉
《数据结构》
---使用C语言
实验报告
姓名:
学号:
专业班号:
实验日期:
2012.11.22
问题描述:
在一个带权图中,从一个结点到另一个结点存在的路径上所经过的边的权值之和为路径的长度,求一个结点到另一个结点最短路径的问题,用狄克斯特拉算法实现。
基本要求:
(1)、测试数据和结点顺序表最大数据限制MaxSize,最大结点限制MaxVertice,最大权值MaxWeight在程序中确定;
(2)、图的存储结构是邻接矩阵存储结构;
(3)、初始状态时结点集合S中只包含源点记为v0。
(4)、集合S中每加入一个新的结点u都要修改从源点到另一个结点集合T中剩余结点的当前最短路径长度值。
(5)、集合T中的结点全部加入到集合S中停止。
测试数据:
Chara[]={'A','B','C','D','E','F'};
RowColWeightrcw[]={{0,2,5},{0,3,30},{1,0,2},{1,4,8},{2,1,15},
{2,5,7},{4,3,4},{5,3,10},{5,4,18}};
算法思想:
设置两个结点的集合S和T,集合S中存放已找到最短路径的结点,集合T中存放当前还未找到最短路径的结点。
初始状态时,集合S中只包含源点,设为v0,然后不断从集合T中选择到源点v0路径长度最短的结点u加入到集合S中,集合S中每加入一个新的结点u都要修改从源点v0到集合T中剩余节点的当前最短路径长度值,集合T中各结点的新的当前最短路径长度值,为原来的最短路径长度值与从源点过结点u到达该结点的路径长度中的较小者。
此过程不断重复,直到集合T中的结点全部加入到集合S中为止。
模块划分:
(1)“AdjMG..h”邻接矩阵存储结构存贮所需要的图的数据操作,“AdjMGC.h”创建所需要的图,图的创建函数voidCreatGraph();
(2)“Dijkstra.h”狄克斯特拉算法函数求最短路径;
(3)main.cpp为主函数,直接利用四个头文件中的操作函数实现最短路径的查找。
数据结构:
1)数据类型Datatype定义如下:
typedefstruct
{
DataTypelist[MaxSize];
intsize;
}SeqList;
2)图的结构体定义如下:
typedefstruct
{
SeqListVertices;
intedge[MaxVertices][MaxVertices];
intnumOfEdges;
}AdjMGraph;
3)边信息结构体定义如下:
typedefstruct
{
introw;
intcol;
intweight;
}RowColWeight;
源程序:
/////////////////////////////SeqList.h////////////////////////////
typedefstruct
{
DtaTypelist[MaxSize];
intsize;
}SeqList;
//初始化顺序表L
voidListInitiate(SeqList*L)
{
L->size=0;//定义初始数据元素个数
}
//求当前元素个数
intListLength(SeqListL)//返回顺序表L的当前数据元素个数
{
returnL.size;
}
//插入数据元素
intListInsert(SeqList*L,inti,DataTypex)
//在顺序表L的第i(0<=i<=size)个位置前插入数据元素值x
//插入成功返回1,插入失败返回0
{
intj;
if(L->size>=MaxSize)
{
printf("顺序表已满无法插入!
\n");
return0;
}
elseif(i<0||i>L->size)
{
printf("参数i不合法!
\n");
return0;
}
else
{
//为插入做准备
for(j=L->size;j>i;j--)L->list[j]=L->list[j-1];
L->list[i]=x;//插入x
L->size++;//元素个数加1
return1;
}
}
//删除数据元素
intListDelete(SeqList*L,inti,DataType*x)
//删除顺序表L中位置为i(0<=i<=size-1)的数据元素并存放到x中
//删除成功返回1,删除失败返回0
{
intj;
if(L->size<=0)
{
printf("顺序表已空无数据元素可删!
\n");
return0;
}
elseif(i<0||i>L->size-1)
{
printf("参数i不合法");
return0;
}
else
{
*x=L->list[i];//保存删除的元素到x中
//依次前移
for(j=i+1;j<=L->size-1;j++)L->list[j-1]=L->list[j];
L->size--;//数据元素个数减1
return1;
}
}
//取数据元素
intListGet(SeqListL,inti,DataType*x)
//取顺序表L中第i个数据元素存于x中,成功返回1,失败返回0
{
if(i<0||i>L.size-1)
{
printf("参数i不合法!
\n");
return0;
}
else
{
*x=L.list[i];
return1;
}
}
/////////////////////////AdjMG.h//////////////////////////
#include"SeqList.h"/*包含顺序表头文件*/
typedefstruct
{
SeqListVertices;/*存放结点的顺序表*/
intedge[MaxVertices][MaxVertices];/*存放边的邻接矩阵*/
intnumOfEdges;/*边的条数*/
}AdjMG;/*图的结构体定义*/
voidInitiate(AdjMG*G,intn)/*初始化*/
{
inti,j;
for(i=0;ifor(j=0;j{
if(i==j)G->edge[i][j]=0;
elseG->edge[i][j]=MaxWeight;
}
G->numOfEdges=0;/*边的条数置为0*/
ListInitiate(&G->Vertices);/*顺序表初始化*/
}
voidInsertVertex(AdjMG*G,DataTypevertex)/*在图G中插入结点vertex*/
{
ListInsert(&G->Vertices,G->Vertices.size,vertex);/*顺序表尾插入*/
}
voidInsertEdge(AdjMG*G,intv1,intv2,intweight)
/*在图G中插入边,边的权为weight*/
{
if(v1<0||v1>G->Vertices.size||v2<0||v2>G->Vertices.size)
{
printf("参数v1或v2越界出错!
\n");
exit
(1);
}
G->edge[v1][v2]=weight;
G->numOfEdges++;
}
voidDeleteEdge(AdjMW*G,intv1,intv2)/*在图G中删除边*/
{
if(v1<0||v1>G->Vertices.size||v2<0||v2>G->Vertices.size||v1==v2)
{
printf("参数v1或v2越界出错!
\n");
exit
(1);
}
if(G->edge[v1][v2]==MaxWeight||v1==v2)
{
printf("该边不存在!
\n")
exit(0);
}
G->edge[v1][v2]=MaxWeight;
G->numOfEdges--;
}
voidDeleteVerten(AdjMG*G,intV)/*删除结点V*/
{
intn=ListLength(G->Vertices),i,j;
DataTypex;
for(i=0;ifor(j=0;jif((i==v||j==v)&&G->edge[i][j]>0&&G->edge[i][j]G->numOfEdges--;/*计算被删除边*/
for(i=v;ifor(j=0;jG->edge[i][j]=G->edge[i+1][j];
for(i=0;ifor(j=v;jG->edge[i][j]=G->edge[i][j+1];
ListDelete(&G->Vertices,v,&x);/*删除结点*/
}
intGetFirstVex(AdjMGG,intv)
/*在图G中寻找序号为V的结点的第一个邻接结点*/
/*如果这样的邻接结点存在,返回该邻接结点的序号;否则返回-1*/
{
intcol;
if(v<0||v>=G.Vertices.size)
{
printf("参数v1越界出错!
\n");
exit
(1);
}
for(col=0;colif(G.edge[v][col]>0&&G.edge[v][col]return-1;
}
intGetNextVex(AdjMGG,intv1,intv2)
/*在图G中寻找v1结点的邻接结点v2的下一个邻接结点*/
/*如果这样的邻接结点存在,返回该邻接结点的序号;否则返回-1*/
/*v1和v2都是相应结点的序号*/
{
intcol;
if(v1<0||v1>=G.Vertices.size||v2<0||v2>=G.Vertices.size)
{
printf("参数v1或v2越界出错!
\n");
exit
(1);
}
for(col=v2+1;colif(G.edge[v1][col]>0&&G.edge[v1][col]return-1;
}
////////////////////////////////////////////AdjMGC.h///////////////////////////////////////////////
typedefstruct
{
introw;/*行下标*/
intcol;/*列下标*/
intweight;/*权值*/
}RowColWeight;/*边信息结构体定义*/
voidCreatGraph(AdjMG*G,DtaTypeV[],intn,RowColWeightE[],inte)
//在图G中插入n个结点信息V和e条边信息E
{
inti,k;
Initiate(G,n);//结点顺序表初始化
for(i=0;iInsertVertex(G,V[i]);//结点插入
for(k=0;kInsertEdge(G,E[k].row,E[k].col,E[k].weight);//边插入
}
////////////////////////////////////////Dijkstra.h/////////////////////////////////////////////
voidDijkstra(AdjMGG,intv0,intdistance[],intpath[])
//带权图G从下标v0结点到其他结点的最短距离distance和最短路径下标path
{
intn=G.Vertices.size;
int*s=(int*)malloc(sizeof(int)*n);
intminDis,i,j,u;
//初始化
for(i=0;i{
distance[i]=G.edge[v0][i];
s[i]=0;
if(i!
=v0&&distance[i]elsepath[i]=-1;
}
s[v0]=1;//标记结点v0已从集合T加入到S中
//在当前还未找到最短路径的结点集中选取具有最短距离的结点u
for(i=1;i{
minDis=MaxWeight;
for(j=0;jif(s[j]==0&&distance[j]{
u=j;
minDis=distance[j];
}
//当已不再存在路径时算法结束;此语句对非联通图是必须的
if(minDis==MaxWeight)return;
s[u]=1;//标记结点u已从集合T加入到集合S中
//修改从v0到其他结点的最短距离和最短路径
for(j=0;jif(s[j]==0&&G.edge[u][j]{
//结点v0经结点u到其他结点的最短距离和最短路径
distance[j]=distance[u]+G.edge[u][j];
path[j]=u;
}
}
}
/////////////////////////////////////////main.cpp/////////////////////////////////////////
#include
#include
#include
typedefcharDataType;
#defineMaxSize100
#defineMaxVertices10
#defineMaxWeight10000
#include"AdjMG.h"
#include"AdjMGC.h"
#include"Dijkstra.h"
voidmain(void)
{
AdjMGg;
chara[]={'A','B','C','D','E','F'};
RowColWeightrcw[]={{0,2,5},{0,3,30},{1,0,2},{1,4,8},{2,1,15},{2,5,7},{4,3,4},{5,3,10},{5,4,18}};
inti,n=6,e=9;
intdistance[6],path[6];
CreatGraph(&g,a,n,rcw,e);
Dijkstra(g,0,distance,path);
printf("从结点%c到其他各结点的最短距离为:
\n",g.Vertices.list[0]);
for(i=0;iprintf("到结点%c的最短距离为%d:
\n",g.Vertices.list[i],distance[i]);
printf("从结点%c到其他各结点最短路径的前一结点为:
\n",g.Vertices.list[0]);
for(i=0;iif(path[i]!
=-1)
printf("到结点%c的前一结点%c:
\n",g.Vertices.list[i],g.Vertices.list[path[i]]);
}
测试情况: