图的应用
2016-12-16 22:29
169 查看
图的应用
一、实验目的
1、使学生可以巩固所学的有关图的基本知识。
2、熟练掌握图的存储结构。
3、掌握如何应用图解决各种实际问题。
二、实验内容
本次实验提供若干个题目,难易程度不等,学生可以根据自己的情况选做至少一题。
题目一:最小生成树问题
[问题描述]
若要在n个城市之间建设通信网络,只需要假设n-1条线路即可。如何以最低的经济代价建设这个通信网,是一个网的最小生成树问题。
[基本要求]
1.利用克鲁斯卡尔算法求网的最小生成树。
2.要求输出各条边及它们的权值。
[实现提示]
通信线路一旦建成,必然是双向的。因此,构造最小生成树的网一定是无向网。设图的顶点数不超过30个,并为简单起见,网中边的权值设成小于100的整数。
图的存储结构的选取应和所作操作相适应。为了便于选择权值最小的边,此题的存储结构既不选用邻接矩阵的数组表示法,也不选用邻接表,而是以存储边(带权)的数组表示图。
[测试数据]
由学生依据软件工程的测试技术自己确定。
1、总体设计(设计思想):
克鲁斯卡尔算法的核心在于每次寻找最短的边加入图中,并且不能形成环路。还需要结合并查集解决环路问题。
2、详细设计及重要代码:
用结构体数组保存每一条边的信息(起点、终点、权值),然后从小到大排序,输出的时候判断是否能构成环路,需要用到并查集的思想。
3、效果展示及截图:
4、程序清单:
题目二:拓扑排序的应用
试编程,为某校软件专业的四年全部课程做一个排课方案。
[测试数据]
自行设计
1、总体设计(设计思想):
邻接矩阵记录拓扑图的信息,数组记录每个点的入度,每次去找入度为一的顶点,并输出,即拓扑排序。
2、详细设计:
邻接矩阵记录拓扑图的信息,数组记录每个点的入度,每次去找入度为1的顶点,并输出,然后把这个点的入度减一即可。
3、功能展示及截图:
4、程序清单:
题目三:最短路径问题
[问题描述]
给定一个无向网,可以求得任意一对顶点之间的最短路径。
[基本要求]
以邻接矩阵为存储结构,实现弗洛伊德算法求解每一对顶点之间的最短路径及最短路径长度。
[测试数据]
由学生依据软件工程的测试技术自己确定。
1、总体设计(设计思想):
题目意思很简单,即求最短路径,利用弗洛伊德算法求解每一对顶点之间的最短路径及最短路径长度。
2、详细设计及重要代码:
讲每一对顶点之间的权值保存在邻接矩阵中,利用弗洛伊德算法求解每一对顶点之间的最短路径及最短路径长度,并另外定义一个数组来保存路径。
3、功能展示及截图:
4、程序清单:
一、实验目的
1、使学生可以巩固所学的有关图的基本知识。
2、熟练掌握图的存储结构。
3、掌握如何应用图解决各种实际问题。
二、实验内容
本次实验提供若干个题目,难易程度不等,学生可以根据自己的情况选做至少一题。
题目一:最小生成树问题
[问题描述]
若要在n个城市之间建设通信网络,只需要假设n-1条线路即可。如何以最低的经济代价建设这个通信网,是一个网的最小生成树问题。
[基本要求]
1.利用克鲁斯卡尔算法求网的最小生成树。
2.要求输出各条边及它们的权值。
[实现提示]
通信线路一旦建成,必然是双向的。因此,构造最小生成树的网一定是无向网。设图的顶点数不超过30个,并为简单起见,网中边的权值设成小于100的整数。
图的存储结构的选取应和所作操作相适应。为了便于选择权值最小的边,此题的存储结构既不选用邻接矩阵的数组表示法,也不选用邻接表,而是以存储边(带权)的数组表示图。
[测试数据]
由学生依据软件工程的测试技术自己确定。
1、总体设计(设计思想):
克鲁斯卡尔算法的核心在于每次寻找最短的边加入图中,并且不能形成环路。还需要结合并查集解决环路问题。
2、详细设计及重要代码:
用结构体数组保存每一条边的信息(起点、终点、权值),然后从小到大排序,输出的时候判断是否能构成环路,需要用到并查集的思想。
3、效果展示及截图:
4、程序清单:
#include<iostream> #include<stdio.h> #include<string> #include<string.h> #include<cstring> #include<stack> #include<queue> #include<algorithm> #include<math.h> #include<vector> #include<iomanip> #include<map> using namespace std; #define MAXEDGE 20 #define MAXVEX 20 #define INF 1<<30 struct Edge { int id; int begin; int end; int weight; }edge[30]; //对边集数组Edge结构的定义 int parent[30]; bool cmp(Edge a,Edge b) { if(a.weight!=b.weight) return a.weight<b.weight; return a.id<b.id; } int find(int x) { if(parent[x]!=x) return parent[x]=find(parent[x]); return x; } void uni(int x,int y) { parent[find(x)]=find(y); } int main() { int n,m,k,g; cout<<"=====以存储边(带权)的数组表示图====="<<endl; cout<<"请输入顶点数:"<<endl; cin>>m; cout<<"请输入边的条数:"<<endl; cin>>n; for(int i=0;i<n;i++) { cout<<"请输入第"<<i+1<<"条边所连接的两个顶点和权值(顶点编号0到n-1):"<<endl; cin>>edge[i].begin>>edge[i].end>>edge[i].weight; edge[i].id=i; } sort(edge,edge+n,cmp); for(int i=0;i<n;i++) parent[i]=i; cout<<"最小生成树为:"<<endl; for(int i=0;i<n;i++) { k=find(edge[i].begin); g=find(edge[i].end); if(k!=g) { parent[find(k)]=find(g); cout<<"("<<k<<","<<g<<")"<<edge[i].weight<<endl; } } cout<<endl<<endl; return 0; } /* 11 7 0 1 7 0 3 5 1 2 8 1 3 9 1 4 7 2 4 5 3 4 15 3 5 6 4 5 8 4 6 9 5 6 11 */
题目二:拓扑排序的应用
试编程,为某校软件专业的四年全部课程做一个排课方案。
[测试数据]
自行设计
1、总体设计(设计思想):
邻接矩阵记录拓扑图的信息,数组记录每个点的入度,每次去找入度为一的顶点,并输出,即拓扑排序。
2、详细设计:
邻接矩阵记录拓扑图的信息,数组记录每个点的入度,每次去找入度为1的顶点,并输出,然后把这个点的入度减一即可。
3、功能展示及截图:
4、程序清单:
#include<iostream> #include<stdlib.h> #include<stdio.h> #define MAX 100 using namespace std; char name[MAX]; void toposort(int map[MAX][MAX],int indegree[MAX],int n) { int i,j,k; for(i=0;i<n;i++) //遍历n次 { for(j=0;j<n;j++) //找出入度为0的节点 { if(indegree[j]==0) { indegree[j]--; cout<<"课程序号是:"<<j<<" 课程名称是:"<<name[j]<<endl; for(k=0;k<n;k++) //删除与该节点关联的边 { if(map[j][k]==1) { indegree[k]--; } } break; } } } } int main() { int n,m,i,x,y; //n:关联的边数,m:节点数 int map[MAX][MAX]; //邻接矩阵 int indegree[MAX]; //入度 cout<<endl<<"=======根据拓扑图做一个排课方案======="<<endl<<endl; while(1) { cout<<"请输入拓扑关系图的边数和顶点数(以 0 0 结束):"<<endl; scanf("%d %d",&n,&m); if(m==0&&n==0)break; memset(map,0,sizeof(map)); memset(indegree,0,sizeof(indegree)); for(int i=0;i<m;i++) { cout<<"请输入课程名字(char型字符):"<<endl; cin>>name[i]; } cout<<endl<<"构建拓扑图,依据输入课程时的序号"<<endl<<endl; for(i=0;i<n;i++) { cout<<"请输入第"<<i+1<<"条边的起点和终点:"<<endl; scanf("%d %d",&x,&y); if(!map[x][y]) { map[x][y]=1; indegree[y]++; } } cout<<endl<<"排课顺序可以是:"<<endl; toposort(map,indegree,m); cout<<endl<<endl; } return 0; } /* 6 6 a b c d e f 5 2 5 0 4 0 4 1 2 3 1 3 */
题目三:最短路径问题
[问题描述]
给定一个无向网,可以求得任意一对顶点之间的最短路径。
[基本要求]
以邻接矩阵为存储结构,实现弗洛伊德算法求解每一对顶点之间的最短路径及最短路径长度。
[测试数据]
由学生依据软件工程的测试技术自己确定。
1、总体设计(设计思想):
题目意思很简单,即求最短路径,利用弗洛伊德算法求解每一对顶点之间的最短路径及最短路径长度。
2、详细设计及重要代码:
讲每一对顶点之间的权值保存在邻接矩阵中,利用弗洛伊德算法求解每一对顶点之间的最短路径及最短路径长度,并另外定义一个数组来保存路径。
3、功能展示及截图:
4、程序清单:
#include<iostream> #include<stdio.h> #include<string> #include<string.h> #include<cstring> #include<stack> #include<queue> #include<algorithm> #include<math.h> #include<vector> #include<iomanip> #include<map> using namespace std; #define MAX 9999999 #define N 1005 int mp ,path ; int main() { int n,a,b; cout<<endl<<"====以邻接矩阵为存储结构实现弗洛伊德算法===="<<endl<<endl; while(1) { cout<<"请输入顶点个数(0结束):"<<endl; cin>>n; if(n==0)break; cout<<"请输入连接矩阵(n*n,不连通输入-1):"<<endl; for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { cin>>mp[i][j]; if(mp[i][j]==-1) mp[i][j]=MAX; //如果两个点不连同,则把其赋为最大值 path[i][j]=j; } } for(int k=1;k<=n;k++) //flod算法核心代码 { for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(mp[i][j]>mp[i][k]+mp[k][j]) { mp[i][j]=mp[i][k]+mp[k][j]; path[i][j]=path[i][k]; } } while(1) { cout<<"请输入起点和终点(输入-1 -1时结束):"<<endl; cin>>a>>b; if(a==-1&&b==-1)break; printf("从 %d 到 %d :\n",a,b); int x=a; printf("路径: %d",a); while(x!=b) { cout<<"-->"<<path[x][b]; x=path[x][b]; } cout<<endl; cout<<"一共花费: "<<mp[a][b]<<endl<<endl;; } } return 0; } /* 5 0 3 22 -1 4 3 0 5 -1 -1 22 5 0 9 20 -1 -1 9 0 4 4 -1 20 4 0 1 3 3 5 2 4 -1 -1 0 */
相关文章推荐
- nginx的sysV init脚本
- 烂泥:VMWare Workation双网卡配置IP地址 推荐
- 个人作业
- sprint3(第八天)
- PYTHON-1
- bLue的文件查找器
- STM32F030低温下RTC不工作
- numpy基本使用方法示例
- 虚拟空间与地址空间的管理
- 代码中适配
- centos7 网卡名字改为eth0
- Android----按钮单击事件的四种写法
- python菜鸟
- HEVC码率控制(二):从compressGOP()到compressSlice()
- 【从零开始学习MySql数据库】(1)建表与简单查询
- 细节成就未来(结构化数组)
- SSH框架之Hibernate的主配置文件
- Java_Ant详解
- Java动态绑定与静态绑定
- 一句printf搞定一个数组的矩阵输出。