图的最短路径(算法与数据结构课程设计)
图的最短路径
一、问题描述
最小生成树是一个有n个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有个结点,并且有保持图连通的最小的边,最小生成树在实际问题中具有一定的应用价值,如在城市之间建设网络,要保证网络的连通性,求最经济的设计方法。求解最小生成树时,可以采用普里母算法和克鲁斯卡尔算法。
二、基本要求
1、选择合适的储存结构,完成网的建立;
2、利用普里母算法求网的最少生成树,并输出结果;
3、利用克鲁斯卡尔求网的最少生成树,并输出结果;
4、采用邻接矩阵和邻接表两种储存结构;
三、测试数据
对右图进行测试
右图是6个顶点的10个边的连通图
六个顶点分别是
v1 v2 v3 v4 v5 v6
边和边上的权植分别是
v1 v2 6
v1 v3 1
v1 v4 5
v2 v3 5
v2 v5 3
v3 v4 5
v3 v5 6
v3 v6 4
v4 v6 2
v5 v6 6
四、算法思想
克鲁斯卡尔算法思想是:假设连通图N=(V,{E}),则令最小生成树的初始状态为只有n个顶点而无边的非连通图T=(V,{ }),图中每个顶点自成一个连通分量。在E中选择代价最小的边,若该边依附的顶点落在T中不同的连通分量上,则将此边加入到T中,否则舍去此边而选择下一条代价最小的边。以此类推,直至T中所有顶点都在同一连通分量上为止。
普里母算法思想是:假设N=(V,{E})是连通图,TE是N上最小生成树中边的集合。算法从U={u0}(u0∈V),TE={ }开始,重复执行下述操作:在所有u∈U,v∈V —U的边(u,v)∈E中找一条代价最小的边(u0,v0)并入集合TE,同时v0并入U,直至U=V为止。此时TE中必有n-1条边,则T=(V,{TE})为N的最小生成树。为实现这个算法需附设辅助数组closedge,以记录从U到V-U具有最小代价的边。对每个顶点vi ∈V-U,在辅助数组中存在一个相应分量closedge[i-1],它包括两个域,其中lowcost储存该边的权。显然,closedge[i-1].lowcost=Min{cost(u,vi)|u∈U},vex∈U}, vex 域存储该边依附的在U中的顶点。
五、模块
克鲁斯卡尔算法和普里母算法都要用到以下的算法
int LocateVex(Mgraph G,Vertex u),矩阵求点u所在位置;
void CreateGraph(Mgraph/ ALGraph &G),建立带权邻接矩阵/邻接表的结构;
void kruskal2(ALGraph G),邻接链表的克鲁斯卡尔算法;
void kruskal(MGraph G),邻接矩阵的克鲁斯卡尔算法;
int minimum(ALGraph/ MGraph G,struct arry wq[]),邻接表/邻接矩阵求最小的权值;
void MiniSpanTree_PRIM1(ALGraph G,VertexType u),邻接表的普里姆算法;
void MiniSpanTree_PRIM2(MGraph G,VertexType u),邻接矩阵的普里姆算法。
六、数据结构//(ADT)
1、邻接表的储存结构如下
邻接表的结点结构信息
typedef struct ArcNode{/*定义边结点*/
int adjvex;/*该弧指向的顶点的位置*/
int weight;/*该弧的权重*/
struct ArcNode *nextarc;/*指向下一条弧的指针*/
}ArcNode;
邻接表的表头向量的结点结构信息
typedef struct VNode{
VertexType data; /*顶点信息*/
ArcNode *firstarc;/*指向第一条依附该顶点的弧的指针*/
}VNode,AdjList[MAX_VERTEX_NUM];//定义图结点
邻接表的表头带权图的结构信息
typedef struct{
AdjList vertices;/*表头向量*/
int vexnum,arcnum;//顶点数和弧数
}ALGraph;//定义图
2、邻接矩阵的储存结构如下
typedef int AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];/*邻接距阵*/ 邻接矩阵带权图的结构信息
struct MGraph
{ Vertex vexs[MAX_VERTEX_NUM];/*顶点向量*/
AdjMatrix arcs;/*邻接矩阵*/
int vexnum,arcnum;/*顶点数和弧数*/
};
七、源程序
#include
#include
#include
#define MAX_NAME 5 /*顶点值最大字符数*/
#define MAX_VERTEX_NUM 20 /*最大顶点数*/
typedef char Vertex[MAX_NAME];/*(邻接矩阵用)顶点名字串*/
typedef char VertexType[MAX_NAME];/*(邻接链表用)顶点名字串*/
typedef int AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];/*邻接距阵*/
/*链表的结点结构信息*/
typedef struct ArcNode{/*定义边结点*/
int adjvex;/*该弧指向的顶点的位置*/
int weight;/*该弧的权重*/
struct ArcNode *nextarc;/*指向下一条弧的指针*/
}ArcNode;
/*表头向量的结点结构信息*/
typedef struct VNode{
VertexType data;/*顶点信息*/
ArcNode *firstarc;/*指向第一条依附该顶点的弧的指针*/
}VNode,AdjList[MAX_VERTEX_NUM];//定义图结点
/*链表带权图的结构信息*/
typedef struct{
AdjList vertices;/*表头向量*/
int vexnum,arcnum;//顶点数和弧数
}ALGraph;//定义图
/*矩阵带权图的结构信息*/
struct MGraph
{ Vertex vexs[MAX_VERTEX_NUM];/*顶点向量*/
AdjMatrix arcs;/*邻接距阵*/
int vexnum,arcnum;/*顶点数和弧数*/
};
struct arry
{ VertexType adjvex;
int lowcost;
}closedge[MAX_VERTEX_NUM];
int LocateVex(MGraph G,Vertex u)//矩阵求点u所在位置{ int i;
for(i=0;i if(strcmp(u,G.vexs[i])==0) return i; return -1; } int LocateVe(ALGraph G,VertexType u)//链表求出点u所在位置{ int i; for(i=0;i if(strcmp(G.vertices[i].data,u) == 0) return i; return -1; } /*============================================*/ /*===========邻接矩阵的克鲁斯卡尔算法=========*/ /*============================================*/ void CreateGraph(MGraph &G)//建立带权邻接矩阵结构 { int i,j,k,w; Vertex va,vb; printf("请输入无向网G的顶点数和边数(分别以空格为分隔):\n"); scanf("%d %d",&G.vexnum,&G.arcnum); printf("请输入%d个顶点的值:\n",G.vexnum,MAX_NAME); for(i=0;i scanf("%s",G.vexs[i]); for(i=0;i for(j=0;j G.arcs[i][j]=0x7fffffff; printf("请输入%d条边各自的起点,终点,权值(分别用空格分隔):\n",G.arcnum); for(k=0;k { scanf("%s%s%d",va,vb,&w); i=LocateVex(G,va); j=LocateVex(G,vb); G.arcs[i][j]=G.arcs[j][i]=w;/*对称*/ } } /*邻接矩阵的克鲁斯卡尔算法*/ void kruskal(MGraph G) { int set[MAX_VERTEX_NUM],i,j;/*set数组用来判断两个点是否在同一个集合里*/ int k=0,a=0,b=0,min=G.arcs[a][b]; for(i=0;i set[i]=i; printf("最小代价生成树的各条边为:\n"); while(k { for(i=0;i for(j=i+1;j if(G.arcs[i][j] { min=G.arcs[i][j]; a=i; b=j; } min=G.arcs[a][b]=0x7fffffff;//将最小权值改成最大值 if(set[a]!=set[b])/*若a、b两个点不在同一集合里,则输出a、b之间的边*/ { /*int s1=set[b];*/ printf("%s-%s\n",G.vexs[a],G.vexs[b]); k++; for(i=0;i if(set[i]==set[b]/*s1*/) set[i]=set[a]; } } } /*邻接矩阵的克鲁斯卡尔算法*/ void k1(){ MGraph g; CreateGraph(g); kruskal(g); } /*============================================*/ /*===========邻接链表的克鲁斯卡尔算法=========*/ /*============================================*/ void CreateGraph(ALGraph &G){ //邻接链表创建带权图 int i,j,k,w; VertexType va,vb; printf("请输入顶点数,边数(请用空格分开):\n"); /*输入顶点数、弧数*/ scanf("%d %d",&G.vexnum,&G.arcnum); printf("请输入各顶点的值:\n"); for(i = 0; i < G.vexnum; ++i)/*初始化顶点值*/ scanf("%s",G.vertices[i].data); for(i = 0; i < G.vexnum; ++i)//初始化vertices数组 G.vertices[i].firstarc=NULL; printf("请输入各边的起点,终点,权值(分别用空格分开):\n"); for(k = 0; k < G.arcnum; ++k){ scanf("%s%s%d",va,vb,&w); i = LocateVe(G,va);/*确定va、vb的位置*/ j = LocateVe(G,vb); ArcNode *p = (ArcNode *)malloc(sizeof(ArcNode)); //申请一个结点空间 p->adjvex = j;//初始化 p->weight = w; p->nextarc = G.vertices[i].firstarc;//插表头 G.vertices[i].firstarc =p; ArcNode *q = (ArcNode *)malloc(sizeof(ArcNode)); q->adjvex = i; q->weight = w; q->nextarc = G.vertices[j].firstarc; G.vertices[j].firstarc = q; } } /*邻接链表的克鲁斯卡尔算法*/ void kruskal2(ALGraph G){ int i,j,min = 0x7fffffff,k = 0;//min用于记录最小权值 int set[MAX_VERTEX_NUM];//用于判断两个点是否在同一集合里 ArcNode *p,*q,*s; for(i = 0; i < G.vexnum; ++i) set[i] = i;//初始化,将每个点自身作为一个集合while(k < G.vexnum - 1){ for(i = 0; i < G.vexnum; ++i){ if(G.vertices[i].firstarc!=NULL){//若第i+1个点没有领边,则下一循环for(p=G.vertices[i].firstarc;p!=NULL;p=p->nextarc)//查找最小权值的边 if(p->weight < min){ min = p->weight; q = p; j = i; } } } if(G.vertices[j].firstarc == q) G.vertices[j].firstarc = q->nextarc; //if-else用于删除最小权值的边 else{ for(p = G.vertices[j].firstarc; p != q; p = p->nextarc) s = p; s->nextarc = q->nextarc; } if(set[j]!=set[q->adjvex]){//判断两点是否在同一集合,若不在,则输出这条边printf("(%s,%s) %d\n",G.vertices[j].data,G.vertices[q->adjvex].data,q->weight); k++; /*int s2=set[j];*/ for(i=0;i if(set[i]==set[j]/*s2*/) set[i]=set[q->adjvex]; } min = 0x7fffffff; //将min置为最大值 } } void k2(){ ALGraph G; CreateGraph(G); kruskal2(G); } /*============================================*/ /*===========邻接矩阵的普里姆算法=========*/ /*============================================*/ int minimum2(MGraph G,struct arry wq[]) { int i,j; for(i=0;i if(wq[i].lowcost!=0&&wq[i].lowcost!=0x7fffffff) break; j=i; for(i=0;i if(wq[j].lowcost>wq[i].lowcost&&wq[i].lowcost!=0) j=i; return j; } void MiniSpanTree_PRIM2(MGraph G, VertexType u) { int i,j,k; k = LocateVex (G,u); for ( j=0; j if (j!=k) { strcpy(closedge[j].adjvex,u); closedge[j].lowcost=G.arcs[k][j]; } } closedge[k].lowcost = 0; for (i=1; i k = minimum2(G,closedge); closedge[k].lowcost = 0; printf("%s%s ",closedge[k].adjvex,G.vexs[k]); for (j=0; j if (G.arcs[k][j]< closedge[j].lowcost&&closedge[j].lowcost!=0) { strcpy(closedge[j].adjvex,G.vexs[k]); closedge[j].lowcost=G.arcs[k][j]; } } } void k3(){ MGraph g; CreateGraph(g); MiniSpanTree_PRIM2(g,"v1"); } /*============================================*/ /*===========邻接表的普里姆算法=========*/ /*============================================*/ int minimum1(ALGraph G,struct arry wq[]) { int i,j; for(i=0;i if(wq[i].lowcost!=0&&wq[i].lowcost!=0x7fffffff) break; j=i; for(i=0;i if(wq[j].lowcost>wq[i].lowcost&&wq[i].lowcost!=0) j=i; return j; } void MiniSpanTree_PRIM1(ALGraph G, VertexType u) { int i,j,k;ArcNode *p; p=(ArcNode*)malloc(sizeof(ArcNode)); k=LocateVe(G,u); for ( j=0; j closedge[j].lowcost=0x7fffffff; for (j=0;j { if(strcmp(G.vertices[j].data,u) == 0) { for(p=G.vertices[k].firstarc;p!=NULL;p=p->nextarc) { closedge[p->adjvex].lowcost=p->weight; strcpy(closedge[p->adjvex].adjvex,u);} //for break; } //if }//for closedge[k].lowcost=0; for (i=1; i k = minimum1(G,closedge); closedge[k].lowcost=0; printf("%s%s ",closedge[k].adjvex,G.vertices[k].data); for (j=0; j for(p=G.vertices[k].firstarc;p!=NULL;p=p->nextarc) if(p->weight {closedge[j].lowcost=p->weight; strcpy(closedge[j].adjvex,G.vertices[k].data);} }} void k4(){ ALGraph G; CreateGraph(G); MiniSpanTree_PRIM1(G,"v1"); } int main() { int cord; do {printf("\n===================================="); printf("\n 主菜单 "); printf("\n 1.邻接矩阵实现克鲁斯算法 "); printf("\n 2.邻接链表实现克鲁斯算法 "); printf("\n 3.邻接矩阵实现普里姆算法 "); printf("\n 4.邻接链表实现普里姆算法 "); printf("\n 5.退出程序 "); printf("\n===================================="); printf("\n 请输入您的选择(1,2,3,4,5) cord="); scanf("%d",&cord); switch(cord) { case 1:k1();break; case 2:k2();break; case 3:k3();break; case 4:k4();break; case 5:exit(0); } }while(cord<=5); system("pause"); } 八、测试情况 程序的测试结果如下: 邻接矩阵实现克鲁斯卡尔运行结果如下 邻接链表实现克鲁斯卡尔如下 邻接矩阵实现普利姆算法如下 邻接链表实现普利姆算法如下 人工验证,都正确 九、参考文献 1、严蔚敏,《数据结构 C语言》,清华大学出版社。 2、谭浩强,《c语言程序设计》,清华大学出版社。 小结 通过本次课程设计,我学到了很多。要写好一个程序必须弄清他的最基本的思路,除此之外要有算法思路,会写一些基本函数,程序不是一个非要一个主要的函数或者程序要写完,最好有几个函数组成,以便于利用。编程不像做其它事,它要求编程人员有非常缜密的思维,很好的整体把握能力和很好的调试程序的能力等。决定程序成功与否的往往既是有程序的整体思路和整体算法,也要特别注重细节,一个程序没有整体思路和整体算法是写不出来的,但是细节错误往往也是程序成功的观念,小细节的错误导致运行不成功,结果错误,感觉所有的功夫都白费了,我在此次课程设计中深有体会。编程不是轻而易举的,必须要考虑什么储存结构更适合那个算法,本次就用邻接矩阵和邻接表,而没用十字链表,十字链表不合适,而且它的操作相对比较复杂,在小程序中没有优势,还有,算法的实现须要哪些变量,变量中信息又需要哪些,中间算法的需要又用到哪些中间变量,这些没有一定的编程语言的基础和编程经验是无法完成的…… 在写程序的过程中我深刻体会到:如果要写程序,一定要有一定的语言基础知识,此外还要有形成的算法思想及一些基本的储存结构都要会写。没有一点点的语言基础理所当然是写不出来的,所以写程序时感觉到当时应该更努力的学习,深刻的体会到“书到用时方恨少”。邻接表和邻接矩阵的储存结构书上给了一个大概的结构,但是要根据需要辨别储存结构中哪些变量要用,哪些不要用,根据需要来取舍,还有一些变量的在不同的地方用不同的用处,要根据所写程序的需要来辨别他的用处不同即它要保存什么变量。当然此次程序设计中普利姆算法书上有一个大致的结构,所以我是根据书上的程序写的,但是中间有好多的函数要自己独立完成,例如求最小权值minimum函数,在写此函数时我多次出错,最后还是在同学的帮助下完成。 此次我领略到以前学习的知识的重要性和分工合作精神的重要性,集体编程和个人编程有很大不同,相互间独立而又紧密联系在一起,如创建带权的邻接矩阵和邻接表时,我是参考以前程序编写的,但是我要知道相应的的算法中需要哪些变量和函数,进而完成编写。还有编程要实用,求最小生成树是为了求图的最短路径,如我编写的两个算法中,带权的图的邻接矩阵和邻接表中的边,我不仅仅要添加边,还要考虑到边的权值,以求最短的路径。在本次课程设计中,虽然以前我对两种算法只有一个大概的整体思路,但是没有一个具体详细的思路,尤其是中间的许多函数不是很了解,但在我不断的查看书籍和多次虚心求教下我还是顺利地完成了。求最短路径问题看似是一个很简单的问题,但在实际的程序编写时如果没有学好C语言和数据结构知识是很难完成。例如,算法思想是解决本问题的根本关键,数据结构课本175页有它的介绍。 从这次课程设计中,我了解到知识的重要性,不论是书本的,还是人际交往上的,让我感受颇深! 实验3:最短路径算法 一、实验目的 通过本实验的学习,理解Floyd(弗洛伊得)最短路径算法的思想 二、实验内容 用C语言编程实现求赋权图中任意两点间最短路径的Floyd算法,并能对给定的两结点自动求出最短路径 三、实验原理、方法和手段 1、Floyd算法的原理 定义:Dk[i,j] 表示赋权图中从结点vi出发仅通过v0,v1,┉,vk-1中的某些结点到达vj的最短路径的长度, 若从vi到vj没有仅通过v0,v1,┉,vk-1 的路径,则D[i,j]=∝即 D-1[i,j] 表示赋权图中从结点vi到vj的边的长度,若没有从结点vi到vj的边,则D[i,j]=∝ D0[i,j] 表示赋权图中从结点vi到vj的”最短”路径的长度, 这条路上除了可能有v0外没有其它结点 D1[i,j] 表示赋权图中从结点vi到vj的”最短”路径的长度, 这条路上除了可能有v0,v1外没有其它结点 ┉┉┉ 根据此定义,D k[i,j]=min{ D k-1[i,j] , D k-1[i,k-1]+D k-1[k-1,j] } 定义:path[i,j]表示从结点vi到vj的“最短”路径上vi的后继结点 四、实验要求 要求输出每对结点之间的最短路径长度以及其最短路径 五、实验步骤 (一)算法描述 Step 1 初始化有向图的成本邻矩阵D、路径矩阵path 若从结点vi到vj有边,则D[i,j]= vi到vj的边的长度,path[i,j]= i; 否则D[i,j]=∝,path[i,j]=-1 Step 2 刷新D、path 对k=1,2,┉n 重复Step 3和Step 4 Step 3 刷新行对i=1,2,┉n 重复Step 4 Step 4 刷新Mij 对j=1,2,┉n 若D k-1[i,k]+D k-1[k,j] 一、课程设计题目:校园最短路径问题 二、课程设计目的: 1.了解并掌握数据结构与算法的设计方法,具备初步的独立分析和设计能力; 2.初步掌握软件开发过程的问题分析、系统设计、程序编码、测试等基本方法和技能; 3.提高综合运用所学的理论知识和方法独立分析和解决问题的能力; 4.训练用系统的观点和软件开发一般规范进行软件开发,培养软件工作者所具备的科学工作方法和作风。 三、课程设计要求: 1.设计的题目要求达到一定的工作量(300行以上代码),并具有一定的深度和难度。 2.编写出课程设计报告书,内容不少于10页(代码不算)。 四、需求分析: 1、问题描述 图的最短路径问题是指从指定的某一点v开始,求得从该地点到图中其它各地点的最短路径,并且给出求得的最短路径的长度及途径的地点。除了完成最短路径的求解外,还能对该图进行修改,如顶点以及边的增删、边上权值的修改等。 校园最短路径问题中的数据元素有: a) 顶点数 b) 边数 c) 边的长度 2、功能需求 要求完成以下功能: a)输出顶点信息:将校园内各位置输出。 b)输出边的信息:将校园内每两个位置(若两个位置之间有直接路径)的 距离输出。 c)修改:修改两个位置(若两个位置之间有直接路径)的距离,并重新输 出每两个位置(若两个位置之间有直接路径)的距离。 d)求最短路径:输出给定两点之间的最短路径的长度及途径的地点或输出 任意一点与其它各点的最短路径。 e)删除:删除任意一条边。 f)插入:插入任意一条边。 3、实现要点 a) 对图的创建采用邻接矩阵的存储结构,而且对图的操作设计成了模板类。 为了便于处理,对于图中的每一个顶点和每一条边都设置了初值。 b) 为了便于访问,用户可以先输出所有的地点和距离。 c) 用户可以随意修改两点之间好的距离。 d) 用户可以增加及删除边。 e) 当用户操作错误时,系统会出现出错提示。 五、概要设计: 滁州学院 课程设计报告 课程名称:数据结构 设计题目:关键路径问题 院部:计算机与信息工程 专业:网络工程 组别:第六组 起止日期:2012年4月9日~2012年6月24日指导教师:赵玉艳 计算机与信息工程学院二○一二年制 课程设计题目关键路径问题 组长柯焱芳学号2011211384 班级网工113班院部计算机工程系专业网络工程 组员靳梦婷李鹏飞陆勇刘宜雨 指导教师赵玉艳 课程设计目的1.巩固和加深学生对数据结构课程基本知识的理解,综合该课程中所学的理论知识,独立或联合完成一个数据结构应用课题的设计; 2.根据选题需要,通过查阅手册和文献资料,培养分析和解决实际问题的能力; 3.熟练掌握图的各种基本数据结构的定义、存储结构和相应的算法,并可熟练利用c语言进行实现; 4.具有一定的算法设计和分析能力,掌握选用合适的数据结构解决实际问题的方法; 5.学会撰写课程设计报告,能做出简单答辩; 6.培养严肃认真的工作作风和严谨求实的科学态度。 课程设计所需环境 ⑴实验设备:PC机⑵操作系统:Windows XP ⑶开发环境:Visio C++6.0 课程设计任务要求要求学生理解图的特征和性质,掌握各类图的存储结构、相关操作的程序实现以及图的应用,能够利用图的遍历、图的最小生成树、最短路径、关键路径、拓扑排序等原理解决实际问题。 课程设计工作进度计划 序号起止日期工作内容分工情况 1 4.09-4.16 选题与分析课题内容, 查找资料柯焱芳:选题与分析课题内容 陆勇靳梦婷李鹏飞刘宜雨:查找资料 2 4.17-4.25 编写创建图,求最大路 径的函数刘宜雨靳梦婷:创建图李鹏飞陆勇:求最大路径 3 4.26- 5.16 编写总代码和主函数 (求关键路径) 柯焱芳:编写总代码和主函数(求关键路径) 4 5.17-5.2 5 对程序输入改写柯焱芳靳梦婷:对程序输入改写 5 5.26-6.10 对程序进行测试柯焱芳靳梦婷刘宜雨陆勇李鹏飞 6 6.11-6.24 整理文档与总结柯焱芳陆勇 指导教师签字:年月日院(系)审核意见 院长(主任)签字:年月日 硕士生考查课程考试试卷 考试科目:MATLAB教程 考生姓名:考生学号: 学院:专业: 考生成绩: 任课老师(签名) 考试日期:20 年月日午时至时 《MATLAB 教程》试题: A 、利用MATLA B 设计遗传算法程序,寻找下图11个端点的最短路径,其中没有连接的端点表示没有路径。要求设计遗传算法对该问题求解。 a d e h k B 、设计遗传算法求解f (x)极小值,具体表达式如下: 3 21231(,,)5.12 5.12,1,2,3 i i i f x x x x x i =?=???-≤≤=? ∑ 要求必须使用m 函数方式设计程序。 C 、利用MATLAB 编程实现:三名商人各带一个随从乘船渡河,一只小船只能容纳二人,由他们自己划行,随从们密约,在河的任一岸,一旦随从的人数比商人多,就杀人越货,但是如何乘船渡河的大权掌握在商人手中,商人们怎样才能安全渡河? D 、结合自己的研究方向选择合适的问题,利用MATLAB 进行实验。 以上四题任选一题进行实验,并写出实验报告。 选择题目: A 一、问题分析(10分) 1 4 10 11 如图如示,将节点编号,依次为 1.2.3.4.5.6.7.8.9.10.11,由图论知识,则可写出其带权邻接矩阵为: 0 2 8 1 500 500 500 500 500 500 500 2 0 6 500 1 500 500 500 500 500 500 8 6 0 7 500 1 500 500 500 500 500 1 500 7 0 500 500 9 500 500 500 500 500 1 500 500 0 3 500 2 500 500 500 500 500 1 500 3 0 4 500 6 500 500 500 500 500 9 500 4 0 500 500 1 500 500 500 500 500 2 500 500 0 7 500 9 500 500 500 500 500 6 500 7 0 1 2 500 500 500 500 500 500 1 500 1 0 4 500 500 500 500 500 500 500 9 2 4 0 注:为避免计算时无穷大数吃掉小数,此处为令inf=500。 问题要求求出任意两点间的最短路径,Floyd 算法采用的是在两点间尝试插入顶点,比较距离长短的方法。我思考后认为,用遗传算法很难找到一个可以统一表示最短路径的函数,但是可以对每一对点分别计算,然后加入for 循环,可将相互之间的所有情况解出。观察本题可发现,所有节点都是可双向行走,则可只计算i 到j 的路径与距离,然后将矩阵按主对角线翻折即可得到全部数据。 二、实验原理与数学模型(20分) 实现原理为遗传算法原理: 按所选择的适应度函数并通过遗传中的复制、交叉及变异对个体进行筛选,使得适应度高的个体被保留下来,组成新的群体,新的群体既继承了上一代的信息,又优于上一代。这样周而复始,群体中个体适应度不断提高,直到满足一定的条件。 数学模型如下: 设图G 由非空点集合12{,...}n V V V V = 和边集合12{,...}m E e e e = 组成,其中121221(,)e ,P ,)(P ,P ), i i i i i i i i e P P E P =∈≠且若(则G 为一个有向图; 又设i e 的值为i a ,12{,...},m A a a a = 故G 可表示为一个三元组{,,}G P E A = 则求最短路径的数学模型可以描述为: 中南大学 《数据结构》课程设计 题目第9题 Dijkstra算法求最短路径 学生姓名 XXXX 指导教师 XXXX 学院信息科学与工程学院 专业班级 XXXXXXX 完成时间 XXXXXXX 目录 第一章问题分析与任务定义---------------------------------------------------------------------3 1.1 课程设计题目-----------------------------------------------------------------------------3 1.2 原始数据的输入格式--------------------------------------------------------------------3 1.3 实现功能-----------------------------------------------------------------------------------3 1.4 测试用例-----------------------------------------------------------------------------------3 1.5 问题分析-----------------------------------------------------------------------------------3 第二章数据结构的选择和概要设计------------------------------------------------------------4 2.1 数据结构的选择--------------------------------------------------------------------------4 2.2 概要设计-----------------------------------------------------------------------------------4 第三章详细设计与编码-----------------------------------------------------------------------------6 3.1 框架的建立---------------------------------------------------------------------------------6 3.2 点结构体的定义---------------------------------------------------------------------------7 3.3 创立带权值有向图------------------------------------------------------------------------8 3.4 邻接矩阵的显示---------------------------------------------------------------------------9 3.5 递归函数的应用---------------------------------------------------------------------------10 3.6 Dijkstra算法实现最短路径--------------------------------------------------------------10 第四章上机调试------------------------------------------------------------------------------------11 4.1 记录调试过程中错误和问题的处理---------------------------------------------------11 4.2 算法的时间课空间性能分析------------------------------------------------------------11 4.3 算法的设计、调试经验和体会---------------------------------------------------------11 第五章测试结果-----------------------------------------------------------------------------------12 第六章学习心得体会-----------------------------------------------------------------------------12 第七章参考文献-----------------------------------------------------------------------------------12 附录------------------------------------------------------------------------------------------------------12 《数据结构的课程设计》 报告 题目:关键路径问题设计与实现班级:1612401 学号:161240113 姓名:张修鸣 指导老师:孙涵 完成日期:2014.1.3 目录 一.需求分析. 二.程序主要功能. 三.程序运行平台. 四.程序类说明. 五.模块分析. 六.存在的不足与对策. 七.体验感悟 八.程序源代码. 需求分析 设计并实现关键路径的一种应用。 程序主要功能 (1)实现拓扑排序和关键路径的发现。 (2)给出一个具体的应用环境。 程序运行平台 该程序是用VC++6.0制做的,使用Microsoft Visual C++ 6.0运行该程序,具体操作是:打开Microsoft Visual C++ 6.0,菜单栏里点文件→打开工作区→找到“图书管理系统.dsw”这个文件→打开,或者在资源管理器中双击该文件,此时,VC++6.0会自动打开,并载入该系统相关资源,点击Run命令菜单或者或用快捷键Ctrl+F5运行该程序。 程序类说明 typedef struct node{ int adjvex; //邻接点域 int time;//活动持续时间 struct node *next; }Node; Node *p; typedef struct VertexNode{ int vertex; //顶点域 int indegree; //入度域 Node *firstedge; //边表头指针 }AdjList[20]; typedef struct{ AdjList adjlist;//邻接表 int Dian;//顶点数 int Bian; //边数 }ALGraph 函数分析: void CreateALGraph(ALGraph *&G) //建立有向图 int TopoSort(ALGraph *G,int s[20],int ve[20]) //拓扑排序并求各顶点事件的最早发生时间及拓扑逆序列 int CriticalPath(ALGraph *G)//求关键路径和关键活动 模块分析 文件的信息 关键活动与关键路径 存在的不足与对策 由于自身能力有限,所以没有设计好交互界面。 在设计过程中由于设计者的编程功底欠缺,因此学习过程较为艰辛,需要解决的问题也比较多。在以后的学习中,应该循序渐进,不可急于求成,先打好基础,这样才能更好地发展。 《数据结构课程设计》最短路径问题实验报告 目录 一、概述 0 二、系统分析 0 三、概要设计 (1) 四、详细设计 (5) 4.1建立图的存储结构 (5) 4.2单源最短路径 (6) 4.3任意一对顶点之间的最短路径 (7) 五、运行与测试 (8) 参考文献 (11) 附录 (12) 交通咨询系统设计(最短路径问题)一、概述 在交通网络日益发达的今天,针对人们关心的各种问题,利用计算机建立一个交通咨询系统。在系统中采用图来构造各个城市之间的联系,图中顶点表示城市,边表示各个城市之间的交通关系,所带权值为两个城市间的耗费。这个交通咨询系统可以回答旅客提出的各种问题,例如:如何选择一条路径使得从A城到B城途中中转次数最少;如何选择一条路径使得从A城到B城里程最短;如何选择一条路径使得从A城到B城花费最低等等的一系列问题。 二、系统分析 设计一个交通咨询系统,能咨询从任何一个城市顶点到另一城市顶点之间的最短路径(里程)、最低花费或是最少时间等问题。对于不同的咨询要求,可输入城市间的路程、所需时间或是所需费用等信息。 针对最短路径问题,在本系统中采用图的相关知识,以解决在实际情况中的最短路径问题,本系统中包括了建立图的存储结构、单源最短问题、对任意一对顶点间最短路径问题三个问题,这对以上几个问题采用了迪杰斯特拉算法和弗洛伊德算法。并未本系统设置一人性化的系统提示菜单,方便使用者的使用。 三、概要设计 可以将该系统大致分为三个部分: ①建立交通网络图的存储结构; ②解决单源最短路径问题; ③实现两个城市顶点之间的最短路径问题。 迪杰斯特拉算法流图: 一、实验目的 学习掌握图的存储结构 利用最短路径算法,通过java编程实现最短路径输出。 二、实验环境 Eclipse平台 三、实验过程 最短路径算法问题是计算机科学、运筹学、地理信息系统和交通诱导、导航系统等领域研究的一个热点。传统的最短路径算法主要有Floyd算法和Dijkstra算法。Floyd 算法用于计算所有结点之间的最短路径。Dijkstra算法则用于计算一个结点到其他所有结点的最短路径。本程序利用Dijkstra算法用java语言实现最短路径的可视化。 流程: 画无向邻接矩阵邻接矩阵初始化求取最短路径 Java文件如下 M ain.java 文件: import java.awt.BorderLayout; import java.awt.Color; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.util.StringTokenizer; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.border.TitledBorder; public class Main { public static void main(String args[]) { new UI("最短路径"); } } @SuppressWarnings("serial") class UI extends JFrame implements ActionListener, ItemListener { JFrame frame; JButton button; 数据结构第20次课 (续表) 思考.题 作业题试对下图所示的AOE网络,解答下列问题。 (1) 这个工程最早可能在什么时间结束。 (2) 求每个事件的最早开始时间Ve[i]和最迟开始时间Vl[I]。 (3) 求每个活动的最早开始时间e( )和最迟开始时间l( )。 (4) 确定哪些活动是关键活动。画出由所有关键活动构成的图,指出哪些活动加速可使整个工程提前完成。 *参考资料《数据结构辅导与提高》,徐孝凯编著,清华大学出版社 《数据结构习题解答与考试指导》,梁作娟等编著,清华大学出版社 授课内容 关键路径 对整个工程和系统,人们关心的是两个方面的问题: 一)工程能否顺利进行(对AOV网进行拓扑排序) 二)估算整个工程的完成所必须的最短时间(对AOE网求关键路径) 1. AOE-网 } 与AOV-网相对应的是AOE-网(Activity On Edge),即边表示活动的网。 AOE-网是一个带权的有向无环图,其中,顶点表示事件(Event),弧表示活 动,权表示活动持续的时间。通常,AOE-网可用来估算工程的完成时间。 例:下图是一个假想的有11项活动的AOE-网。其中有9个事件v 1 , v 2 ,…,v 9 ,每个事件表示在它之前的活动已经完成,在它之后的活动可以 开始。如v 1 表示整个工程开始,v 9 表示整个工程结束,v 5 表示a 4 和a 5 已经 完成,a 7 和a 8 可以开始。与每个活动相联系的数是执行该活动所需的时间。 比如,活动a 1 需要6天,a 2 需要4天等。 和AOV-网不同,对AOE-网有待研究的问题是: (1)完成整项工程至少需要多少时间 (2)哪些活动是影响工程进度的关键 2. 关键路径 由于在AOE-网中有些活动可以并行地进行,所以完成工程的最短时间 是从开始点到完成点的最长路径的长度(这里所说的路径长度是指路径上 各活动持续时间之和,不是路径上弧的数目)。路径长度最长的路径叫做关 备注: 回顾 唐山学院 数据结构课程设计 题目栈的基本操作及其应用 系 (部) 计算机科学与技术系 班级 16计本(2) 姓名周登旺 学号 4164001232 指导教师郭琳虹 2018 年 1 月8日至2018 年1 月12日共1 周 数据结构课程设计任务书 课程设计成绩评定表 1.引言 在计算机系统中,栈则是一个具有以上属性的动态内存区域。程序可以将数据压入栈中,也可以将数据从栈顶弹出。在i386机器中,栈顶由称为esp的寄存器进行定位。压栈的操作使得栈顶的地址减小,弹出的操作使得栈顶的地址增大。首先系统或者数据结构栈中数据内容的读取与插入(压入push和弹出pop)是两回事!插入是增加数据,弹出是删除数据,这些操作只能从栈顶即最低地址作为约束的接口界面入手操作,但读取栈中的数据是随便的没有接口约束之说。很多人都误解这个理念从而对栈产生困惑。而系统栈在计算机体系结构中又起到一个跨部件交互的媒介区域的作用即cpu与内存的交流通道,cpu只从系统给我们自己编写的应用程序所规定的栈入口线性地读取执行指令,用一个形象的词来形容它就是pipeline(管道线、流水线)。cpu内部交互具体参见EU与BIU的概念介绍。栈作为一种数据结构,是一种只能在一端进行插入和删除操作的特殊线性表。它按照后进先出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据(最后一个数据被第一个读出来)。栈具有记忆作用,对栈的插入与删除操作中,不需要改变栈底指针。 栈是允许在同一端进行插入和删除操作的特殊线性表。允许进行插入和删除操作的一端称为栈顶(top),另一端为栈底(bottom);栈底固定,而栈顶浮动;栈中元素个数为零时称为空栈。插入一般称为进栈(PUSH),删除则称为退栈(POP)。栈也称为后进先出表。栈可以用来在函数调用的时候存储断点,做递归时要用到栈! 一、基本概念 栈(stack)在计算机科学中是限定仅在表尾进行插入或删除操作的线形表。 栈是一种数据结构,是只能在某一端插入和删除的特殊线性表。它按照先进后出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据(最后一个数据被第一个读出来)。 栈是允许在同一端进行插入和删除操作的特殊线性表。允许进行插入和删除操作的一端称为栈顶(top),另一端为栈底(bottom);栈底固定,而栈顶浮动;栈中元素个数为零时称为空栈。插入一般称为进栈(PUSH),删除则称为退栈(POP)。栈也称为后进先出表(LIFO表),栈可以用来在函数调用的时候存储断点,做递归时要用到栈! 本课程设计涉及的主要内容是对栈进行基本操作和实现栈的一些实际应用,在课程设计中,系统开发平台为Windows 7。程序设计语言使用Visual c++。程序的运行平台为Windows 2000/XP/7/10。 /* 2问题分析 本次课程设计主要介绍栈的概念和栈的基本操作和栈的两种存储结构及其应用。其中栈的基本操作主要包括置空栈,判断栈空,进栈,出栈,取栈顶元素。栈的两种存储 云南财经大学信息学院学生综合性与设计性实验报告 (2013—2014 学年第 2 学期) 周次:第7周日期:2014年 4 月 17 日地点: 一、实验内容与目的 1.内容 查看“最短路径.swf”,选择熟悉的程序设计语言定义有向图,根据动画演示求取从有向图任一结点到其他结点的最短路径。 2.实验目的 了解最短路径的概论,掌握求最短路径的方法。 二、实验原理或技术路线(可使用流程图描述) 实验原理:(李燕妮负责设计,周丽琼负责编程) 图是由结点的有穷集合V和边的集合E组成,求最短路径用迪杰斯特拉算法: 1)适用条件&范围: a) 单源最短路径(从源点s到其它所有顶点v); b) 有向图&无向图(无向图可以看作(u,v),(v,u)同属于边集E的有向图) c) 所有边权非负(任取(i,j)∈E都有Wij≥0); 2)算法描述: a)初始化:dis[v]=maxint(v∈V,v≠s); dis[s]=0; pre[s]=s; S={s}; b)For i:=1 to n 1.取V-S中的一顶点u使得dis[u]=min{dis[v]|v∈V-S} 2.S=S+{u} 3.For V-S中每个顶点v do Relax(u,v,Wu,v) c)算法结束:dis[i]为s到i的最短距离;pre[i]为i的前驱节点 三、实验环境条件(使用的软件环境) Microsoft Visual C++6.0 四、实验方法、步骤(列出程序代码或操作过程) /*本程序的功能是求图中任意两点间的最短路径*/ #include 第 6 章图 课后习题讲解 1. 填空题 ⑴设无向图G中顶点数为n,则图G至少有()条边,至多有()条边;若G为有向图,则至少有()条边,至多有()条边。 【解答】0,n(n-1)/2,0,n(n-1) 【分析】图的顶点集合是有穷非空的,而边集可以是空集;边数达到最多的图称为完全图,在完全图中,任意两个顶点之间都存在边。 ⑵任何连通图的连通分量只有一个,即是()。 【解答】其自身 ⑶图的存储结构主要有两种,分别是()和()。 【解答】邻接矩阵,邻接表 【分析】这是最常用的两种存储结构,此外,还有十字链表、邻接多重表、边集数组等。 ⑷已知无向图G的顶点数为n,边数为e,其邻接表表示的空间复杂度为()。 【解答】O(n+e) 【分析】在无向图的邻接表中,顶点表有n个结点,边表有2e个结点,共有n+2e个结点,其空间复杂度为O(n+2e)=O(n+e)。 ⑸已知一个有向图的邻接矩阵表示,计算第j个顶点的入度的方法是()。 【解答】求第j列的所有元素之和 ⑹有向图G用邻接矩阵A[n][n]存储,其第i行的所有元素之和等于顶点i的()。 【解答】出度 ⑺图的深度优先遍历类似于树的()遍历,它所用到的数据结构是();图的广度优先遍历类似于树的()遍历,它所用到的数据结构是()。 【解答】前序,栈,层序,队列 ⑻对于含有n个顶点e条边的连通图,利用Prim算法求最小生成树的时间复杂度为(),利用Kruskal 算法求最小生成树的时间复杂度为()。 【解答】O(n2),O(elog2e) 【分析】Prim算法采用邻接矩阵做存储结构,适合于求稠密图的最小生成树;Kruskal算法采用边集数组做存储结构,适合于求稀疏图的最小生成树。 ⑼如果一个有向图不存在(),则该图的全部顶点可以排列成一个拓扑序列。 【解答】回路 青岛理工大学琴岛学院 设计报告 课题名称:求解最优交通路径 学院:计算机工程系 专业班级:计算机科学与技术 学号:####### 学生:** 指导教师:** 青岛理工大学琴岛学院教务处 2011 年 7 月 7日 图1 B.具体功能实现及相应的弗洛伊德算法 首先,建立查询信息对话框,使用户能够录入需要查询的城市代号,并显示路径长度及最短路径沿途经过的城市。并相应地添加如下变量int m_v0;int m_v1;int m_lj;CString m_zd; 具体代码如下: #define MAXV 25 //最大顶点个数 #define INF 32767 //用32767表示∞ //以下定义邻接矩阵类型 typedef struct { int no; //顶点编号 char name[10]; //顶点名称 } VertexType; //顶点类型 typedef struct //图的定义 { int edges[MAXV][MAXV]; //邻接矩阵 int vexnum,arcnum; //顶点数,弧数 VertexType vexs[MAXV]; //存放顶点信息 } MGraph; //图的邻接矩阵类型 1.通过函数CreatUDN()存放城市路径信息,输入顶点之间的路径长度,创建带权图的邻接矩阵。 void CTDialog::CreatUDN() { MGraph *g=(MGraph*)malloc(sizeof(MGraph)); int i,j; for(i=0;i 中国矿业大学矿业工程学院 实验报告 课程名称计算机软件设计基础 姓名 xxxx 班级采矿10-8班学号 xxxxx 日期 2012年10月 成绩教师 xxxx 3.2算法步骤: (1)输入e条弧 实验六:编程实现Dijkstra 算法求最短路问题. 1.需求分析: 首先让用户输入一个带权的有向图,输入时可通过一对一对输入存在弧的两个弧头与弧尾顶点以及弧上的权值从而输入整个有向图。用户输入一对对弧后,我们可以采用数组的形式来进行存储每个顶点之间的权值,最后由用户输入该有向图的源点(即每个最短路径的起点),要求源点必须为刚才输入的各顶点中的某一个,如果用户输入错误,程序要给出错误信息提示并退出程序。然后,我们可以设计一个Graph这样的类,将对关系的各种操作放入其中,然后我们在主函数中调运这个类就可以实现最短路问题的求解了。 2.概要设计: ①.构造一个新的类Graph: class Graph { private: int arcs[MAX][MAX],Path[MAX][MAX],D[MAX]; int arcnum,vexnum,weight,v0; Type a,b,vexs[MAX]; public: void Creat_Graph(); void Show_ShortestPath(); void ShortestPath_DIJ(); }; ②.结构化调用类中方法的主函数: int main() { Graph 数据结构课程设计:拓扑排序和关键路径 1 ABSTRACT 1.1图和栈的结构定义 struct SqStack////栈部分 { SElemType *base;//栈底指针 SElemType *top;//栈顶指针 int stacksize;//栈的大小 int element_count;//栈中元素个素 }; /////////AOE网的存储结构 struct ArcNode //表结点 { int lastcompletetime;//活动最晚开始时间 int adjvex; //点结点位置 int info; //所对应的弧的权值 struct ArcNode *next;//指向下一个表结点指针 }; struct VNode //点结点 { VertexType data; //结点标志 int indegree; //该结点入度数 int ve; //记录结点的最早开始时间 int vl; //记录结点的最晚开始时间 struct ArcNode *first_out_arc; //存储下一个出度的表结点struct ArcNode *first_in_arc;//存储下一个入度的表结点 }; struct ALGraph { VNode *vertices; //结点数组 int vexnum; //结点数 int arcnum; //弧数 int kind; //该图的类型 }; 2系统总分析 2.1关键路径概念分析 2.1.1什么是关键路径 关键路径法(Critical Path Method, CPM)最早出现于20世纪50年代,它是通过分析项目过程中哪个活动序列进度安排的总时差最少来预测项目工期的网络分析。这种方法产生的背景是,在当时出现了许多庞大而复杂的科研和工程项目,这些项目常常需要运用大量的人力、物力和财力,因此如何合理而有效地对这些项目进行组织,在有限资源下以最短的时间和最低的成本费用下完成整个项目就成为一个突出的问题,这样CPM就应运而生了。对于一个项目而言,只有项目网络中最长的或耗时最多的活动完成之后,项目才能结束,这条最长的活动路线就叫关键路径(Critical Path),组成关键路径的活动称为关键活动。 2.1.2关键路径特点 关键路径上的活动持续时间决定了项目的工期,关键路径上所有活动的持续时间总和就是项目的工期。 关键路径上的任何一个活动都是关键活动,其中任何一个活动的延迟都会导致整个项目完工时间的延迟。 数据结构与算法课程实验报告实验四:图的相关算法应用 姓名:王连平 班级:09信科2班 学号:I09630221 实验四图的相关算法应用 一、实验内容 求有向网络中任意两点之间的最短路。 二、实验目的 掌握图和网络的定义,掌握图的邻接矩阵、邻接表和十字链表等存储表示。掌握图的深度和广度遍历算法,掌握求网络的最短路的标号法和floyd算法。 三、问题描述 对于下面一张若干个城市以及城市间距离的地图,从地图中所有可能的路径中求出任意两个城市间的最短距离及路径,给出任意两个城市间的最短距离值及途径的各个城市。 四、问题的实现 4.1数据结构的抽象数据类型定义和说明 1) typedef struct ArcCell{//储存弧信息 int Distance; ArcCell *info;//此项用来保存弧信息,,在本实验中没有相关信息要保存 }ArcCell,AdjMatrix[ MAX_VERTEX_NUM][ MAX_VERTEX_NUM]; typedef struct{//储存顶点信息 string vexs[ MAX_VERTEX_NUM];//顶点向量 AdjMatrix arcs;//邻接矩阵 int vexnum , arcnum;//图的当前顶点数和弧数 }MGraph; 顶点信息和弧信息都是用来建立一个有向网G 2) d[v][w];//G中各对顶点的带权长度 若P[v][w][u]为TRUE,则u是从v到w当前求得最短路径上的顶点 4.2主要的实现思路 首先通过一个函数(CreateDN)建立图的邻接矩阵储存方式,一次输入某条弧的起点,终点,和权值。通过调用Locate函数来找到该弧在邻接矩阵中的相应位置。 其次运用弗洛伊德算法来求各定点的最短路劲,具体思路为:如果从v到w有弧,则存在一条长度为arcs[v][w]的路径,该路径不一定是最短路径。考虑路径(v,u,w)是否存在,若存在,比较(v,w)和(v,u,w)的长度,取较短者为从v到w的中间点序号不大于0的最短路径。以此类推,每次增加一个点,从而求出任意两点间的最短路径。这样,经过n次比较后,所求得的必为从v到w的最短路径。按此方法,可以同时求得任意两点间的最短路径。 五、主要源程序代码(包含程序备注) #include实验三 最短路径的算法(离散数学实验报告)
数据结构,课程设计,校园最短路径问题
关键路径问题报告
MATLAB实验报告,遗传算法解最短路径以及函数最小值问题讲解
数据结构课程设计报告Dijkstra算法求最短路径
关键路径问题设计与实现
《数据结构课程设计》最短路径问题实验报告
最短路径实验报告
第20讲-关键路径与最短路径
栈的课程设计完整版
最短路径实验报告
数据结构与算法第6章图答案
数据结构课程设计报告_最短路径C++
关键路径的查找实验报告
最短路径_Dijkstra算法__实验报告
数据结构课程设计:拓扑排序和关键路径复习进程
实验四图的最短路径弗洛伊德算法实现