数据结构与算法说明书.docx
- 文档编号:10818115
- 上传时间:2023-02-23
- 格式:DOCX
- 页数:30
- 大小:97.87KB
数据结构与算法说明书.docx
《数据结构与算法说明书.docx》由会员分享,可在线阅读,更多相关《数据结构与算法说明书.docx(30页珍藏版)》请在冰豆网上搜索。
数据结构与算法说明书
数据结构与算法课程设计
题目:
求素数问题
猴子吃桃问题
跳马问题
排序重构问题。
目录
目录2
摘要4
一.求素数问题5
1.数据结构设计5
2.算法设计5
3.调试分析6
4.测试结果6
5.源程序(带注释)6
二.构造可以使n个城市连接的最小生成树8
1.数据结构设计9
2.算法设计9
3.调试分析10
4.测试结果11
5.源程序(带注释)12
三.猴子吃桃问题19
.数据结构设计19
2.算法设计19
3.调试分析21
4.测试结果21
5.源程序(带注释)22
4.排序重构问题24
1.数据结构设计24
2.算法设计24
3、流程图如下:
25
4、调试分析25
5、测试结果25
6、源程序(带注释)26
总结30
参考文献31
致谢31
摘要
此报告是关于四个问题的设计:
求素数问题、猴子吃桃子问题、跳马问题、哈夫曼的编/译码系统。
1.求素数问题。
埃拉托色尼筛法(SieveofEratosthenes)是一种用来求所有小于N的素数的方法。
从建立一个整数2~N的表着手,寻找i˂
的整数,编程实现此算法,并讨论运算时间。
(1)
2.猴子吃桃子问题。
有一群猴子摘了一堆桃子,他们每天都吃当前桃子的一半且再多吃一个,到了第10天就只余下一个桃子。
用多种方法实现求出原来这群猴子共摘了多少个桃子。
要求:
1)采用数组数据结构实现上述求解;2)采用链式数据结构实现上述求解;3)采用递归实现上述求解。
(2)
3.跳马问题。
要求在64个国际象棋格子,任意位置放一个马,如何不重复地把格子走完。
(3)
4.排序重构问题。
令A为一个由N个已特殊排序数组成的数列:
A1,A2,…,AN,其中A1=0。
令B为N(N-1)/2个数(定义为Dij=Ai-Aj(i>j))组成的数列。
例如,A=0,1,5,8,那么D=1,3,4,5,7,8。
请完成:
a)编写程序,根据A构造D;
编写程序,构造与D相对应的某一个数列A,注意A不是唯一的。
。
1)编译的语言:
C语言
2)编译环境:
VisualC++6.0
关键词:
递归,链表,栈和队列,猴子吃桃,跳马,排序重构
C语言数据结构顺序表链表数组
一.求素数问题
埃拉托色尼筛法(SieveofEratosthenes)是一种用来求所有小于N的素数的方法。
从建立一个整数2~N的表着手,寻找i˂
的整数,编程实现此算法,并讨论运算时间。
(1)
1.数据结构设计
定义一个线性表顺序存储结构,用来求所有小于N的素数
typedefintDataType;//数据类型
typedefstruct{
DataTypedata[maxsize];定义一个一维数组
intlength;//线性表中实际元素的个数
}Seqlist;
2.算法设计
用一个循环结构判断是否为素数,如果是素数则返回1,负责返回0。
intsushu(DataType&i)
{
intm;
if(i==1)
return0;//不是素数
for(m=2;m
{
if(i%m==0)
return0;//不是素数
}
return1;//判断为素数,返回为1
}
3.调试分析
断一个数是否为素数的问题,例如数字I,求解其2-i-1求余数,若为0,则不是素数,相反为素数。
时间复杂度的分析:
算法的时间复杂度O(L.length-1)+O(m)。
4.测试结果
图1数问题截图
程序运行结果如图所示,当输入素数5时,显示出1-5之间的素数2,3,5.
5.源程序(带注释)
#include
#include
#definemaxsize200
#defineFALSE0
typedefintDataType;
typedefstruct{
DataTypedata[maxsize];
intlength;
}Seqlist;//结点结构
intsushu(DataTypei){
intm;
if(i==1)
return0;
for(m=2;m
if(i%m==0)
return0;
}
return1;
}
intm;intj;inti=0;intk=0;
intmain(){
SeqlistL;
L.length=maxsize;
for(j=2;j<=L.length;j++){
L.data[j-1]=j;
printf("%d\t",L.data[j-1]);
}
printf("\n");
printf("inputm:
\n");
scanf("%d",&m);
if(m>L.length)returnFALSE;
printf("1至m之间的素数从小到大分别为:
\n");
for(i=1;i<=m;i++)
L.data[i-1]=i;
for(i=1;i<=m;i++)
if(sushu(L.data[i-1])){
k++;
printf("%d\t",L.data[i-1]);//符号"\t"的作用是横向制表。
}
printf("\n总共%d个。
\n",k);
return0;}
二.构造可以使n个城市连接的最小生成树
问题描述:
给定一个地区的n个城市间的距离网,用Prim算法或Kruskal算法建立最小生成树,并计算得到的最小生成树的代价。
(4)
要求:
1)城市间的距离网采用邻接矩阵表示,邻接矩阵的存储结构定义采用课本中给出的定义,若两个城市之间不存在道路,则将相应边的权值设为自己定义的无穷大值.要求在屏幕上显示得到的最小生成树中包括了哪些城市间的道路,并显示得到的最小生成树的代价。
2)表示城市间距离网的邻接矩阵(要求至少6个城市,10条边);
3)最小生成树中包括的边及其权值,并显示得到的最小生成树的代价。
1.数据结构设计
定义一个线性表顺序存储结构,用来求所有小于N的素数
typedefintDataType;//数据类型
typedefstruct{
DataTypedata[maxsize];定义一个一维数组
intlength;//线性表中实际元素的个数
}Seqlist;
2.算法设计
克鲁斯卡尔算法的基本思想是:
假设连通网=(V,{E}),则令最小生成树的初始状态为只有n顶点而无边的非连通图T=(V,{}),图中每个顶点自成一个连通分量。
在E中选择代价最小的边,若该边依附的顶点落在T中不同的连通分量上,则将此边加入到T中,否则舍去此边而选择下一条代价最小的边。
依此类推,直至T中所有顶点都在同一个连通分量上为止。
voidKruskal(graph*g){
intans=0,i,j,k=0;/*ans用来记录生成最小树的权总值*/
intindex;
intcount=0;/*记录打印边的条数*/
for(i=0;i<(g->n);i++)/*初始化数组pre[x],rank[x]*/
set(i);
for(i=0;i<(g->n);i++)
{
for(j=i+1;j<(g->n);j++)
{
p[++k].str=i;
p[k].end=j;
p[k].dis=g->adj[i][j];/*先把所有城市之间的路段看成边*/
}
}
for(i=0;i { index=i; for(j=i+1;j<=k;j++) if(p[j].dis index=j; temp=p[index]; p[index]=p[i]; p[i]=temp; } for(i=0;i if(find(p[i].str)! =find(p[i].end)) /*如果这两点连接在一起不构成一个回路,则执行下面操作*/ { printf("\t第%d条路段为: %d--%d,权值为%d\n",++count,p[i].str,p[i].end,p[i].dis); /*将这条边的起点、终点打印出来*/ ans+=p[i].dis;/*说明这条路段要用*/ Union(p[i].str,p[i].end); } } printf("\t遍历所有城市得到最小生成树的代价为: %d\n\n",ans); } 3.调试分析 程序执行从主函数main()开始,首先在运行界面上显示菜单,调用菜单函menu(),根据switch函数选择调用的函数,其中选择1,调用create()函数,用来创建城市之间距离的图,选择2,调用display()函数,用来显示最小生成树,而函数本身也存在函数的调用,在display()函数中调用Kruskal()函数,该函数式用克鲁斯卡尔算法求最小生成树,而Kruskal()函数中又调用三个函数set(),find(),Union(),它们作用是检验当一条边添加进去,是否会产生回路。 算法的时间复杂度为O( ) 4.测试结果 示例如下: 图2,示例的图图3,对应的最小生成树 运行截图: 图4邻接矩阵 图5最小生成树 5.源程序(带注释) #include #include #include #definemax20//城市间边数 #defineMAX_LNT10//城市数 #defineINF32627//两个城市间无直接路径,用大数32627表示 typedefstructnode/*构造一个结构体,两个城市可以看成起点和终点,之间的道路可以看成一个边*/ { intstr;/*起点*/ intend;/*终点*/ intdis;/*距离*/ }node; nodep[max],temp;/*p记录城市信息*/ typedefstruct{//邻接矩阵存储图结构 intvexs[MAX_LNT];//数组用于存储城市数 intadj[max+1][max+1];//图的邻接矩阵表示 intn,e;//n代表城市数,e代表城市间边数 }graph; intpre[100],rank[100];/*用于判断是否构成回路*/ //intarcs[MAX_LNT][MAX_LNT];/*n表示城市个数,arcs[][]记录城市间权值*/ intmenu()/*菜单函数*/ { intm; printf("求最小生成树\n"); printf("________________________________\n\n"); printf("1输入城市之间的信息\n"); printf("2遍历所有城市生成最小生成树\n"); printf("3退出\n"); printf("________________________________\n\n"); printf("请输入所选功能1-3: \n"); //system("colorE");/*改变界面颜色的*/ scanf("%d",&m); returnm; } voidcreate(graph*g)/*输入城市信息*/ { inti,j,k; printf("输入城市数为: "); scanf("%d",&(g->n)); printf("\n"); printf("输入个城市间边数为: "); scanf("%d",&(g->e)); printf("输入城市的各个顶点为: "); for(i=0;i<(g->n);i++) scanf("%d",&(g->vexs[i]));//顶点存入数组vexs[] printf("输入%d条边,建立邻接矩阵",(g->e)); printf("\n"); for(i=0;i<(g->n);i++)//初始化邻接矩阵 { for(j=0;j<(g->n);j++) { if(i==j) g->adj[i][j]=0; else g->adj[i][j]=INF; } } printf("请输入具有邻接关系的两个顶点在矩阵中所在的行与列及权值: \n"); for(k=0;k<(g->e);k++)//有g->e条边,即有g->e个权值 { scanf("%d,%d",&i,&j); scanf("%d",&g->adj[i][j]); } for(i=0;i<(g->n);i++) for(j=0;j<(g->n);j++) g->adj[j][i]=g->adj[i][j]; printf("图的邻接矩阵如下\n"); for(i=0;i<(g->n);i++)//输出邻接矩阵g { for(j=0;j<(g->n);j++) if(g->adj[i][j]==INF) printf("\t%3s","∞"); else printf("\t%3d",g->adj[i][j]); printf("\n"); } } /*下面三个函数作用是检验当一条边添加进去,是否会产生回路*/ voidset(intx)/*初始化*/ { pre[x]=x; rank[x]=0; } intfind(intx)/*找到这个点的祖先*/ { if(x! =pre[x]) pre[x]=find(pre[x]); returnpre[x]; } voidUnion(intx,inty)/*将这两个添加到一个集合里去*/ { x=find(x); y=find(y); if(rank[x]>=rank[y]) { pre[y]=x; rank[x]++; } elsepre[y]=x; } voidKruskal(graph*g) { intans=0,i,j,k=0;/*ans用来记录生成最小树的权总值*/ intindex; intcount=0;/*记录打印边的条数*/ for(i=0;i<(g->n);i++)/*初始化数组pre[x],rank[x]*/ set(i); for(i=0;i<(g->n);i++) { for(j=i+1;j<(g->n);j++) { p[++k].str=i; p[k].end=j; p[k].dis=g->adj[i][j];/*先把所有城市之间的路段看成一个边*/ } } for(i=0;i { index=i; for(j=i+1;j<=k;j++) if(p[j].dis index=j; temp=p[index]; p[index]=p[i]; p[i]=temp; } for(i=0;i { if(find(p[i].str)! =find(p[i].end))/*如果这两点连接在一起不构成一个回路,则执行下面操作*/ { printf("\t第%d条路段为: %d--%d,权值为%d\n",++count,p[i].str,p[i].end,p[i].dis);/*将这条边的起点、终点打印出来*/ ans+=p[i].dis;/*说明这条路段要用*/ Union(p[i].str,p[i].end); } } printf("\t遍历所有城市得到最小生成树的代价为: %d\n\n",ans); } voiddisplay(graph*g)/*显示生成的最小生成树*/ { if((g->n)==0) { printf("这里没有城市之间的信息\n"); return; } printf("遍历所有城市得到最小生成树为: \n\n\n"); Kruskal(g); } intmain()/*主函数*/ { graph*g=(graph*)malloc(sizeof(graph));//这是给graph类变量*g分配一定的内存空间,分配的空间大小等于结构体graph的大小 while (1) { switch(menu()) { case1: create(g);break;/*输入城市信息*/ case2: display(g);break;/*显示生成的最小生成树*/ case3: exit(0); } } return0;} 三.猴子吃桃问题 有一群猴子摘了一堆桃子,他们每天都吃当前桃子的一半且再多吃一个,到了第10天就只余下一个桃子。 用多种方法实现求出原来这群猴子共摘了多少个桃子。 1) 采用数组数据结构实现上述求解 2) 采用链数据结构实现上述求解 3) 采用递归实现上述求解 .数据结构设计 1数组结构设计 把猴子吃桃的天数倒过来看,以天数座位数组的下表i,剩下桃子的个数a[i]的递推公式为a[i]=(a[i-1]+1)*2。 a[i]实际代表了倒数第i天剩下的桃子的个数。 首先建立一个以天数为下标,以剩余桃子数为元素的数组,规定此数组的通项公式为a[i]=(a[i-1]+1)*2,最后输出第一天的桃子数。 2链式存储结构 建立一个链表,根据每天桃子数与后一天桃子数的关系: n=2*n+2,依次将每天的桃子数存入链表中,最后输出第一天的桃子数。 首先建立一个空的链表,产生一个头结点,并且将头结点的地址赋给某一参数,然后把每天的桃子数从链表的第一个结点插入链表。 最后,第一天的桃子数被最后一个插入链表,成为链表的第一个值,将其赋值给另一个参数并输出,就可以得到第一天的桃子数。 3递归算法 递归算法的设计,利用公式n=2*n+2,定义一个函数ya3,并不断调用算法ya31,求出第一天的桃子数。 2.算法设计 数组数据结构实现: voidya1() { inta[11]={0,0,0,0,0,0,0,0,0,0,0}; a[10]=1;//构造数组 for(inti=10;i>1;i--) a[i-1]=(a[i]+1)*2;//数组的通项公式
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 算法 说明书