当前位置:文档之家› 最小生成树和最短路径数据结构实验

最小生成树和最短路径数据结构实验

实验报告六月 18 2015姓名:陈斌学号:E 专业:13计算机科学与技术数据结构第八次实验学号E专业计算机科学与技术姓名陈斌实验日期教师签字成绩实验报告【实验名称】最小生成树和最短路径【实验目的】(1)掌握最小生成树以及最短路径的相关概念;(2)掌握Prim算法和Kruskal算法;(3)掌握Dijkstra算法【实验内容】采用普里姆算法求最小生成树(1)编写一个算法,对于教材图(a)所示的无向带权图G采用普里姆算法输出从顶点V1出发的最小生成树。

图的存储结构自选。

(2)对于上图,采用克鲁斯卡尔算法输出该图的最小生成树。

(提示:a.先对边按权值从小到大排序,得有序边集E;为所有顶点辅设一个数组Vset,标记各顶点所处的连通分量,初始时各不相同。

b. 依次从E中取出一条边(i,j),检查顶点i和j是否属于同一连通分量,如是,则重取下一条边;否则,该边即为生成树的一条边,输出该边,同时将所有与j处于同一连通分量的顶点的Vset 值都修改为与i的相同。

c.重复b步直至输出n-1条边。

)源代码::#include<>#include<>#include<> dj=INFINITY; /* 网 */}printf("请输入%d条边的顶点1 顶点2 权值(用空格隔开): \n",; for(k=0;k<;++k){scanf("%s%s%d%*c",va,vb,&w); /* %*c吃掉回车符 */i=LocateVex(G,va);j=LocateVex(G,vb);[i][j].adj=[j][i].adj=w; /* 无向 */}=AN;return OK;}typedef struct{ /* 记录从顶点集U到V-U的代价最小的边的辅助数组定义 */VertexType adjvex;VRType lowcost;}minside[MAX_VERTEX_NUM];int minimum(minside SZ,MGraph G){ /* 求的最小正值 */int i=0,j,k,min;while(!SZ[i].lowcost)i++;min=SZ[i].lowcost; /* 第一个不为0的值 */k=i;for(j=i+1;j<;j++)if(SZ[j].lowcost>0)if(min>SZ[j].lowcost){min=SZ[j].lowcost;k=j;}return k;}void MiniSpanTree_PRIM(MGraph G,VertexType u){ /* 用普里姆算法从第u个顶点出发构造网G的最小生成树T,输出T的各条边算法 */int i,j,k;minside closedge;k=LocateVex(G,u);for(j=0;j<;++j) /* 辅助数组初始化 */{if(j!=k){strcpy(closedge[j].adjvex,u);closedge[j].lowcost=[k][j].adj;}}closedge[k].lowcost=0; /* 初始,U={u} */printf("最小代价生成树的各条边为:\n");for(i=1;i<;++i){ /* 选择其余个顶点 */k=minimum(closedge,G); /* 求出T的下一个结点:第K顶点 */printf("(%s-%s)\n",closedge[k].adjvex,[k]); /* 输出生成树的边 */ closedge[k].lowcost=0; /* 第K顶点并入U集 */for(j=0;j<;++j)if[k][j].adj<closedge[j].lowcost){ /* 新顶点并入U集后重新选择最小边 */strcpy(closedge[j].adjvex,[k]);closedge[j].lowcost=[k][j].adj;}}}typedef struct node{int va; <a[j+1].w) { dj!=INFINITY){E[k].va=i;E[k].vb=j;E[k].w=[i][j].adj;k++;}}}Heapsort(E,G);Initialize(G); a];int sn2=Vset[E[j].vb];a],[E[j].vb],E[j].w);k++;for (i=0;i<;i++)if (Vset[i]==sn2)Vset[i]=sn1;}j++;}}void main(){MGraph G;CreateAN(G);cout<<"--------普里姆算法输出从顶点V1出发的最小生成树--------\n"<<endl;MiniSpanTree_PRIM(G,[0]);cout<<"------------------------------------------------------\n"<<endl;cout<<"--------克鲁斯卡尔算法输出从顶点V1出发的最小生成树----\n"<<endl;MiniSpanTree_Kruskal(G);cout<<"------------------------------------------------------"<<endl;}运行结果:采用迪杰斯特拉算法求单源最短路径编写一个算法,采用迪杰斯特拉算法,输出如下图所示的有向带权图G 中从顶点a到其他各顶点的最短路径长度和最短路径。

图的存储结构自源代码::#include<>#include<>#include<> exnum,&(*G).arcnum);printf("请输入%d个顶点的值(<%d个字符):\n",(*G).vexnum,MAX_NAME); for(i=0;i<(*G).vexnum;++i) /* 构造顶点向量 */scanf("%s",(*G).vexs[i]);for(i=0;i<(*G).vexnum;++i) /* 初始化邻接矩阵 */for(j=0;j<(*G).vexnum;++j){(*G).arcs[i][j].adj=INFINITY; /* 网 */}printf("请输入%d条弧的弧尾弧头权值(以空格作为间隔): \n",(*G).arcnum);for(k=0;k<(*G).arcnum;++k){scanf("%s%s%d%*c",va,vb,&w); /* %*c吃掉回车符 */i=LocateVex(*G,va);j=LocateVex(*G,vb);(*G).arcs[i][j].adj=w; /* 有向网 */}(*G).kind=DN;return OK;}typedef int QElemType;/*单链队列--队列的链式存储结构 */typedef struct QNode{QElemType data;struct QNode *next;}QNode,*QueuePtr;typedef struct{QueuePtr front,rear; /* 队头、队尾指针 */}LinkQueue;LinkQueue Q;Status InitQueue(LinkQueue *Q){ /* 构造一个空队列Q */(*Q).front=(*Q).rear=(QueuePtr)malloc(sizeof(QNode)); if(!(*Q).front)exit(OVERFLOW);(*Q).front->next=NULL;return OK;}Status QueueEmpty(LinkQueue Q){ /* 若Q为空队列,则返回TRUE,否则返回FALSE */if==return TRUE;elsereturn FALSE;}Status EnQueue(LinkQueue *Q,QElemType e){ /* 插入元素e为Q的新的队尾元素 */QueuePtr p=(QueuePtr)malloc(sizeof(QNode));if(!p) /* 存储分配失败 */exit(OVERFLOW);p->data=e;p->next=NULL;(*Q).rear->next=p;(*Q).rear=p;return OK;}Status DeQueue(LinkQueue *Q,QElemType *e){ /* 若队列不空,删除Q的队头元素,用e返回其值,并返回OK,否则返回ERROR */ QueuePtr p;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;free(p);return OK;}void ShortestPath_DIJ(MGraph G,int v0,PathMatrix *P,ShortPathTable *D){ /* 用Dijkstra算法求有向网G的v0顶点到其余顶点v的最短路径P[v]及带权长度 *//* D[v]。

若P[v][w]为TRUE,则w是从v0到v当前求得最短路径上的顶点。

*/ /* final[v]为TRUE当且仅当v∈S,即已经求得从v0到v的最短路径算法 */ int v,w,i,j,min;Status final[MAX_VERTEX_NUM];for(v=0;v<;++v){final[v]=FALSE;(*D)[v]=[v0][v].adj;for(w=0;w<;++w)(*P)[v][w]=FALSE; /* 设空路径 */if((*D)[v]<INFINITY){(*P)[v][v0]=TRUE;(*P)[v][v]=TRUE;}}(*D)[v0]=0;final[v0]=TRUE; /* 初始化,v0顶点属于S集 */for(i=1;i<;++i) /* 其余个顶点 */{ /* 开始主循环,每次求得v0到某个v顶点的最短路径,并加v到S集 */min=INFINITY; /* 当前所知离v0顶点的最近距离 */for(w=0;w<;++w)if(!final[w]) /* w顶点在V-S中 */if((*D)[w]<min){v=w;min=(*D)[w];} /* w顶点离v0顶点更近 */final[v]=TRUE; /* 离v0顶点最近的v加入S集 */EnQueue(&Q,v);for(w=0;w<;++w) /* 更新当前最短路径及距离 */{if(!final[w]&&min<INFINITY&&[v][w].adj<INFINITY&&(min+[v][w].adj<(*D)[w]) ){ /* 修改D[w]和P[w],w∈V-S */(*D)[w]=min+[v][w].adj;for(j=0;j<;++j)(*P)[w][j]=(*P)[v][j];(*P)[w][w]=TRUE;}}}}void main(){InitQueue(&Q);int i,j,e,v0=0; /* v0为源点 */MGraph g;PathMatrix p;ShortPathTable d;CreateDN(&g);ShortestPath_DIJ(g,v0,&p,&d);printf("最短路径数组p[i][j]如下:\n");for(i=0;i<;++i){for(j=0;j<;++j)printf("%2d",p[i][j]);printf("\n");}printf("%s到各顶点的最短路径长度为:\n",[0]); for(i=1;i<;++i)printf("%s-%s:%d\n",[0],[i],d[i]);int t[6];//用来存放最短路径的终点的序号(来自队列Q) for(i=0;i<6;i++)DeQueue(&Q,&t[i]);printf("%s到各顶点的最短路径为:\n",[0]);for(i=1;i<;++i){cout<<[0]<<"-"<<[i]<<"的最短路径为:"<<[0]<<' ';for(j=1;j<;j++)if(p[i][t[j-1]]){cout<<[t[j-1]]<<' ';}cout<<endl;}}运行结果:【小结或讨论】(1)通过本次实验,掌握了最小生成树以及最短路径的相关概念,并且会实现Prim算法、Kruskal算法以及Dijkstra算法。

相关主题