报告汇总之c语言数据结构报告篇(四)
通信网的建立
代码区
//
// main.c
// 通信网构建
//
// Created by tianyu on 2019/10/20.
// Copyright © 2019 tianyu. All rights reserved.
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 100
#define wuqiong 100000
//顶点信息
typedef struct Vex
{
char name[MAX][64];
char code[MAX][64];
int length;
}v;
//存放边的信息
typedef struct Edge
{
char vex1[64];
char vex2[64];
int weight;
int A[MAX][MAX];//用来存放邻接矩阵
int vexnumber;//用来存放顶点的数目
int edgenumer;//用来存放边的数目
}e;
//初始化顶点线性表
void initVex (v*L)
{
L->length=-1;
}
//获取顶点
void GetVex (v*L,e*B)
{
initVex(L);
printf("请输入初始的顶点个数:");
scanf("%d",&B->vexnumber);
for (int i=0;i<B->vexnumber;i++)
{
L->length++;
printf("请输入城市名称:");
scanf("%s",L->name[i]);
printf("请输入城市的编号:");
scanf("%s",L->code[i]);
}
}
//获取边的信息并构建邻接矩阵
void GetEdge (e*B,v*L)
{
printf("请输入边的数量:");
scanf("%d",&B->edgenumer);
//初始化邻接矩阵
for (int i=0;i<=B->vexnumber-1;i++)
for (int j=0;j<=B->vexnumber-1;j++)
{
if (i==j)
B->A[i][j]=0;
else
B->A[i][j]=wuqiong;
}
int i,j;
//录入邻接矩阵中边的信息
int m=B->edgenumer;
while (m>0)
{
//录入每条边的基本信息
printf("请输入边的第一个顶点:");
scanf("%s",B->vex1);
getchar();
printf("请输入边的第二个顶点:");
scanf("%s",B->vex2);
printf("请输入两个地点之间的距离:");
scanf("%d",&B->weight);
//找出边的顶点的位置
for (i=0;i<=L->length;i++)
{
if (strcmp(L->name[i], B->vex1)==0)
{
break;
}
}
for (j=0;j<=L->length;j++)
{
if (strcmp(L->name[j], B->vex2)==0)
{
break;
}
}
//将边的值录入邻接矩阵中
B->A[i][j]=B->weight;
B->A[j][i]=B->A[i][j];
m--;
}
for (int i=0;i<=B->vexnumber-1;i++)
{
for (int j=0;j<=B->vexnumber-1;j++)
{
printf("%7d ",B->A[i][j]);
}
printf("\n");
}
}
//删除边的信息
void DeletEdge (e*B,v*L)
{
printf("请输入需要删除边的一个顶点:\n");
scanf("%s",B->vex1);
printf("请输入需要删除边的另一个顶点:\n");
scanf("%s",B->vex2);
int i,j;
for (i=0;i<=L->length;i++)
{
if (strcmp(L->name[i], B->vex1)==0)
{
break;
}
}
for (j=0;j<=L->length;j++)
{
if (strcmp(L->name[j], B->vex2)==0)
{
break;
}
}
B->A[i][j]=B->A[j][i]=wuqiong;
}
//增加边的距离
void addedge (e*B,v*L)
{
printf("请输入需要增加边的一个顶点:\n");
scanf("%s",B->vex1);
printf("请输入需要增加边的另一个顶点:\n");
scanf("%s",B->vex2);
int i,j;
for (i=0;i<=L->length;i++)
{
if (strcmp(L->name[i], B->vex1)==0)
{
break;
}
}
for (j=0;j<=L->length;j++)
{
if (strcmp(L->name[j], B->vex2)==0)
{
break;
}
}
printf("请输入需要增加的距离:");
int h;
scanf("%d",&h);
B->A[j][i]+=h;
B->A[i][j]=B->A[j][i];
}
//城市相关信息的修改
void alter (v*L)
{
printf("1---修改城市名称\n");
printf("2---修改城市编号\n");
printf("请输入需要对城市信息进行的操作:");
int m;
scanf("%d",&m);
printf("请输入需要修改的城市的名字:");
char t[64];
scanf("%s",t);
int i;
for (i=0;i<=L->length;i++)
{
if (strcmp(L->name[i], t)==0)
{
break;
}
}
if (m==1)
{
printf("请输入修改后的城市的名字:");
scanf("%s",t);
strcpy(L->name[i], t);
}
else
{
printf("请输入修改后的城市的编号:");
scanf("%s",t);
strcpy(L->name[i], t);
}
}
void printfedge (e*B)
{
for (int i=0;i<=B->vexnumber-1;i++)
{
for (int j=0;j<=B->vexnumber-1;j++)
{
printf("%7d ",B->A[i][j]);
}
printf("\n");
}
}
//更改图的相关信息
void change (e*B,v*L)
{
printf("1---城市间的距离的增加\n");
printf("2---城市间距离的删除\n");
printf("3---城市的相关信息的修改\n");
printf("4---城市边的关系的显示\n");
printf("请输入需要对城市信息进行的操作:\n");
int m;
scanf("%d",&m);
switch (m)
{
case 2:
DeletEdge(B, L);
break;
case 1:
addedge(B, L);
break;
case 3:
alter(L);
break;
case 4:
printfedge(B);
break;
default:
printf("您输入的指令有误请重新输入!\n");
break;
}
}
//prim算法
void prim (e*B,v*L)
{
int k[100],m=0,i=0,p=0,mix=wuqiong,u=0,n=0,g=0,r[100],w[100];
k[0]=0;
int min=wuqiong;
while (1)
{
for (int j=0;j<L->length+1;j++)
{
if (min>=B->A[i][j]&&B->A[i][j]!=0)
{
p=0;
min=B->A[i][j];
m++;
k[m]=j;
}
else if (j==L->length-1)
p=1;
}
B->A[i][k[m]]=0;
B->A[k[m]][i]=B->A[i][k[m]];
for (int i=0;i<=B->vexnumber-1;i++)
{
for (int j=0;j<=B->vexnumber-1;j++)
{
printf("%7d ",B->A[i][j]);
}
printf("\n");
}
//将未录入边保存
for (int j=0;j<L->length+1;j++)
{
if (B->A[i][j]!=wuqiong&&B->A[i][j]!=0&&j!=k[m])
{
r[n]=B->A[i][j];
w[n]=j;
n++;
}
}
for (int j=0;j<n;j++)
{
if (mix>r[j])
{
p=0;
mix=r[j];
u=j;
}
}
r[u]=wuqiong;
u=w[u];
min=mix;
g=0;
if (p==0)
{
printf("%s->",L->name[i]);
}
if (m!=0)
{
i=k[m];
m--;
p=0;
}
if (u!=0&&p==1&&m==0)
{
p=0;
i=u;
u=0;
}
if (p!=0)
{
printf("%s\n",L->name[i]);
break;
}
}
}
void prim2 (e*B,v*L)
{
int a[100][100];
for (int i=0;i<=B->vexnumber-1;i++)
{
for (int j=0;j<=B->vexnumber-1;j++)
{
a[i][j]=B->A[i][j];
}
}
int i=0,j,min=wuqiong,k[100],p=B->vexnumber,t=0,m=0,n,g[100];
k[t]=0;
n=0;
for (int i=0;i<=L->length+1;i++)
{
g[i]=i;
}
printf("%s->",L->name[m]);//打印第一个顶点
p--;
while (p>=1)
{
int q=t;
t++;
for (i=k[q];q>=0;q--)
{
i=k[q];
n=i;
for (j=0;j<=L->length;j++)
{
if (min>B->A[i][j]&&B->A[i][j]!=0)
{
min=B->A[i][j];
k[t]=j;
m=j;
}
}
}
//将遍历过的元素置零
B->A[n][m]=0;
B->A[m][n]=B->A[n][m];
//打印遍历的元素
if (g[m]!=0)
{
if (p>1)
printf("%s->",L->name[m]);
else
printf("%s\n",L->name[m]);
g[m]=0;
p--;
min=wuqiong;
}
}
for (int i=0;i<=B->vexnumber-1;i++)
{
for (int j=0;j<=B->vexnumber-1;j++)
{
B->A[i][j]=a[i][j];
}
}
}
void kruskal (e*B,v*L)
{
int a[100][100];
for (int i=0;i<=B->vexnumber-1;i++)
{
for (int j=0;j<=B->vexnumber-1;j++)
{
a[i][j]=B->A[i][j];
}
}
//g[]判断顶点是否输出,k[]用来判断是否构成回路
int m=0,n=0,min=wuqiong,k[MAX],g[MAX];
int p=L->length;
//g和k赋处值
for (int i=0;i<=L->length;i++)
{
k[i]=i;
g[i]=i;
}
//打印第一个顶点
printf("%s->",L->name[m]);
p--;
while (p>=0)
{
//找到最短的边
for (int i=0;i<=L->length;i++)
for (int j=0;j<=L->length;j++)
{
if (min>B->A[i][j]&&B->A[i][j]!=0)
{
min=B->A[i][j];
m=i;
n=j;
}
}
//将找到的边变为0
B->A[m][n]=0;
B->A[n][m]=B->A[m][n];
//判断并输出顶点
if (k[m]!=k[n])
{
if (p>=1)
{
if (g[n]!=0)
{
printf("%s->",L->name[n]);
g[n]=0;
}
else
{
printf("%s->",L->name[m]);
g[m]=0;
}
}
else
{
if (g[n]!=0)
{
printf("%s\n",L->name[n]);
g[n]=0;
}
else
{
printf("%s\n",L->name[m]);
g[m]=0;
}
}
for (int i=0;i<=L->length;i++)
{
if (k[i]==n)
k[i]=m;
}
p--;
}
min=wuqiong;
}
for (int i=0;i<=B->vexnumber-1;i++)
{
for (int j=0;j<=B->vexnumber-1;j++)
{
B->A[i][j]=a[i][j];
}
}
}
//菜单系统
void menu (e*B,v*L)
{
int n;
printf("1---创建城市的信息\n");
printf("2---使用prim算法进行通讯网的构建\n");
printf("3---使用kruskal算法进行通讯网的构建\n");
printf("4---对城市的信息进行修改\n");
printf("请输入您需要进行的操作:\n");
scanf("%d",&n);
switch (n)
{
case 1:
GetVex(L, B);
GetEdge(B, L);
break;
case 2:
prim2(B, L);
break;
case 3:
kruskal(B, L);
break;
case 4:
change(B, L);
break;
default:
printf("您输入的指令有误请重新输入!\n");
break;
}
}
int main()
{
v*L;
L=(v*)malloc(sizeof(v));
e*B;
B=(e*)malloc(sizeof(e));
while (1)
{
menu(B, L);
}
return 0;
}
报告区
第一部分:实验分析与设计(可加页)
一、 实验内容描述(问题域描述)
在 n 个城市之间建立通信联络网,则连通 n 个城市只需要 n-1 条线路。要求在 最节省经费的前提下建立这个通信网。
- (1) 完成城市信息的输入。
- (2) 完成城市信息的编辑,包括城市以及城市间距离的增加,删除,信息修改等。
- (3) 允许用户指定下列两种策略进行通信网的构建
1)采用 Prim 算法进行通信网的构建; 2)采用 Kruskal 算法进行通信网的构建;
二、 实验基本原理与设计(数据结构设计与算法设计)
数据结构设计
(1) 利用线性表存储图的顶点信息
(2) 利用领接矩阵存储图的边的信息
算法设计
prim算法
(1) 拟定第一个顶点为初始点查找最短边
(2) 将查找到的最短边的顶点序号存放在k中,并将该边删除
(3) 遍历k中存放的点的所有顶点的边找到最短的边
(4) 重复(2)(3)步直到所有顶点输出
Kuskal 算法
(1) 查找所有边找到最短的边
(2) 将边的两个顶点的记号数组变为其中一个顶点的序号
(3) 删除最短的边
(4) 重复(2)(3)边直到所有顶点输出
三、主要仪器设备及耗材
1.PC机
2.开发环境(比如:VC,Eclipse)
X-code
第二部分:实验调试与结果分析(可加页)
一、 调试过程(包括调试方法描述、实验数据记录,实验现象记录,实验过程发现的问题等)
1.调试方法描述
① 输入c程序,并保存;
② 编译c程序,找出程序的语法错误并改正;
③ 输入测试数据,运行c程序,若有错,查找并修改程序的逻辑错误;
④ 重复②-③步,直到得到正确的运行结果。
2.实验输入/输出数据记录
3.实验过程发现的问题
(1)如何在使用Kruskal方式的时候避免构成回路;设计另一个数组存放集合辅助判断是否构成回路
(2)如何创建一个图表
(3)初始化点集的问题
(4)在利用矩阵后矩阵的值会发生变化;设计一个新的矩阵存储该领接矩阵
二、 实验结果及分析(包括结果描述、实验现象分析、影响因素讨论、综合分析和结论等)
1.结果描述
可以实现题目所需要的所有要求
2.实验现象分析
结果正确
3.影响因素讨论
边的多少直接影响该选择哪一个算法更快
4.算法分析(包括时间和空间)
T(n)=O(n2)
S(n)=O(n2)
5.结论
实验结果均正确,满足题目要求。
三、 实验小结、建议及体会
这次的实验我主要把时间花费在如何创建一个图上,因为对图的理解不是特别透彻所以在第一步总是碰壁。我做prim算法的时间比kruskal的时间要长,应该是做prim的时候无法理解点集和边集,做出来之后,kruskal就顺利了很多。这还是体现了那点,应该要在着手一个程序之前,充分的了解其原理。
从这个实验中更能体现先理解原理在写代码;这是目前写的很长的一个代码了;500多行敲下来不出错只有好好理解原理才能办到。在今后的学习中要对原理进行更加细致的分析。