数据结构实验报告约瑟夫问题求解.docx
- 文档编号:29444368
- 上传时间:2023-07-23
- 格式:DOCX
- 页数:20
- 大小:107.31KB
数据结构实验报告约瑟夫问题求解.docx
《数据结构实验报告约瑟夫问题求解.docx》由会员分享,可在线阅读,更多相关《数据结构实验报告约瑟夫问题求解.docx(20页珍藏版)》请在冰豆网上搜索。
数据结构实验报告约瑟夫问题求解
《计算机软件技术基础》实验报告I—数据结构
实验一、约瑟夫斯问题求解
一、问题描述
1.实验题目:
编号1,2,....,n的n个人顺时针围坐一圈,每人持有一个密码(正整数)。
开始选择一个正整数作为报数上限m,从第一个人开始顺时针自1报数,报到m的人出列,
将他的密码作为新的m值,从他在顺时针方向下一个人开始重新从1报数,直至所有人全部
出列。
2.基本要求:
利用单向循环链表存储结构模拟此过程,按照出列的顺序印出个人的编号。
3.测试数据:
n=7,7个人的密码依次为:
3,1,7,2,4,8,4.m初值为6(正确的出列顺序
应为6,1,4,77,2,3)。
二、需求分析
1.本程序所能达到的基本可能:
该程序基于循环链表来解决约瑟夫问题。
用循环链表来模拟n个人围坐一圈,用链表
中的每一个结点代表一个人和他所代表的密码。
在输入初始密码后m,对该链表进行遍历,
直到第m个结点,令该结点的密码值作为新的密码值,后删除该结点。
重复上述过程,直至
所有的结点被释放空间出列。
2.输入输出形式及输入值范围:
程序运行后提示用户输入总人数。
输入人数n后,程序显示提示信息,提示用户输入第
i个人的密码,在输入达到预定次数后自动跳出该循环。
程序显示提示信息,提示用户输入初始密码,密码须为正整数且不大于总人数。
3.输出形式
提示用户输入初始密码,程序执行结束后会输出相应的出列结点的顺序,亦即其编号。
用户输入完毕后,程序自动运行输出运行结果。
4.测试数据要求:
测试数据n=7,7个人的密码依次为:
3,1,7,2,4,8,4。
m初值为6(正确的出列
顺序应为6,1,4,7,2,3,5)。
三、概要设计
为了实现上述功能,应用循环链表来模拟该过程,用结构体来存放其相应的编号和密码
信息,因此需要循环链表结构体这个抽象数据类型。
1.循环链表结构体抽象数据类型定义:
ADTNode{
数据对象:
D={ai,bi,ci|ai∈int,bi∈int,ci∈(Node*),i=1,2...,n,n
≥0}:
数据关系:
R=?
基本操作:
CreatList(intn)//
Order(intm,node*l)
}ADTnode;
构建循环单链表;
//输出函数,输出出列顺序并删除链表中的结点;
2.ADT的C语言形式说明:
typedefstructNode
{
intnum;//结点的数据域,存放编号;
intword;//结点的数据域,存放密码;
structNode*next;//结点的指针域,存放指向下一结点的指针;
}Node;
Node*CreatList()//建立循环单项链表;
voidOrder(Node*h)//输出出列顺序并删除结点;
3.主程序流程及其模块调用关系:
1).主程序流程:
先提示用户输入相关数据:
总人数,运行循环链表结构体模块,
输入每个人持有的密码
值,创建出新链表,运行输出函数模块,再输入初始密码m值,输出出列序列。
(创建循环单链表模块:
实现链表的抽象数据类型
删除链表结点输出序列模块:
实现输出出列顺序)
2).模块调用关系:
主函数模块
创建循环链表结
体模块
构
删除链表结点输出序
列模块
四、详细设计
1.元素类型、结点类型和结点指针类型:
typedefstructNode//定义一个结构体,包含了每个人的序号和密码
{
intword;
intnum;
structNode*next;
}Node;
2、创建单向循环链表类型:
Node*CreatList()//尾插法创建一个单向循环链表
{
Node*p,*s;
Node*h;//定义头指针
h=(Node*)malloc(sizeof(Node));//
p=h;
h->next=NULL;//初始化链表
申请动态存储空间
printf("第1个人的密码是:
");
scanf("%d",&h->word);
h->num=1;//给头指针赋值
for(i=0;i { s=(Node*)malloc(sizeof(Node)); if(h->next==NULL)h->next=s; elsep->next=s; p=s; printf("第%d个人的密码是: ",i+2); scanf("%d",&s->word); s->num=i+2; } p->next=h; returnh; } 3.删除链表结点输出函数模块: voidOrder(Node*h)// { 输出结果 Node*p; p=h; Node*d; while(p->next! =p) { if(m<2) { p=p->next; } else { for(i=1;i 查找第 m个结点 { p=p->next; } } d=p->next; m=d->word; printf("%d--",d->num); p->next=d->next;//删除结点 p=p->next; free(d); } printf("%d\n",p->num); } 4.主函数: voidmain() { printf(" 试验名称: 约瑟夫斯问题求解 \n"); printf(" 学号: \n"); printf(" 姓名: xx\n"); printf("=========================================================\n"); time_trawtime1; structtm*timeinfo1; time(&rawtime1); timeinfo1=localtime(&rawtime1);//时间函数; printf("程序运行开始,当前日期和时间: %s",asctime(timeinfo1)); printf("请输入总人数: "); scanf("%d",&n); h=CreatList(); printf("请输入初始密码: "); scanf("%d",&m); if(m>n) { printf("初始密码不得大于总人数,请重新输入。 "); scanf("%d",&m); Order(h); } else { Order(h); } time_trawtime2; structtm*timeinfo2; time(&rawtime2); timeinfo2=localtime(&rawtime2); printf("程序运行结束,当前日期和时间: %s",asctime(timeinfo2));while (1); } 5.函数调用关系: 主函数调用Node*CreatList()创建循环单向链表以及调用voidOrder(Node*h)进行 删除结点及输出序列功能。 输出出列序列输出以后,函数调用结束。 五、调试分析 1.程序中将每个人的编号以及密码信息放在链表节点中的数据域,使密码和序号一一对 应。 主函数中,只需要调用链表的操作来实现循环单向链表的创建以及删除结点和输出操作。 2.算法的时空分析: 由于链表采用的都是单向循环链表,而链表中按结点访问的时间性能O(n),n是链表 中结点的个数。 所以,CreatList()以及Order(Node*h)算法的时间复杂度都是O(n)。 输入数据后界面: 八、遇到的问题和解决方法: 1.起初程序编写好后显示0error,但不能正常运行,显示如图 出现随机 数是因为头指针的数据域没有赋值。 增加了对头指针数据域赋值语句后随机数消失。 3.在调试的开始发现输出顺序有错误,经调试发现是因为查找第m个结点时所用的for 循环是从i=1到i 改 正方式是增加一个m<2的特殊情况。 经运行,输出成功。 九、实验收获和感想: 约瑟夫问题是我们学习了软件工程原理与应用这门课后第一次上机编写程序,在以前接触 c语言的时候,我们是没有学过链表的,因此,以前也没有编写过循环链表的程序。 本学期 的软件工程原理与应用开课后,我才真正深入学习和理解了链表结构,通过此次编程对所学知识有了具体的运用,使我对链表结构有了更清晰的了解,从茫然到能正确运用,感觉收获 非常大。 约瑟夫问题虽说是链表问题中相对来说最简单的一个问题,但我刚开始时却是充满了茫然,编出来的程序处处报错。 起初,并没有真正理解建立链表的算法,我单纯仿着课本上的代码照搬上去,不会正确的运用,结果自然是大量的错误。 于是我放下急于求成的心态, 认真看书,认真查资料,终于成功地写出了这个约瑟夫问题的程序。 当它最终0error通过且运行正常时,我的心中充满了激动和满足感,看着自己的作品,很有成就感。 编写完整的程序最考验人的耐心和细心,每一个微不足道的小错误都会导致很长时间的排错。 这次的计算机实践使我在运用中理解了循环链表这部分的知识,为后面的学习和接下来的计算机实践打好了基础,奠定了基石。 十、附录 源程序文件清单: #include #include #include #defineNULL0 typedefstructNode { //定义一个结构体,包含了每个人的序号和密码 intword; intnum; structNode*next; }Node; inti,n,m; Node*h; Node*CreatList() { //尾插法创建一个单向循环链表 Node*p,*s; Node*h;//定义头指针 h=(Node*)malloc(sizeof(Node));//申请动态存储空间 p=h; h->next=NULL;//初始化链表 printf("第1个人的密码是: "); scanf("%d",&h->word); h->num=1;//给头指针赋值 for(i=0;i { s=(Node*)malloc(sizeof(Node)); if(h->next==NULL)h->next=s; elsep->next=s; p=s; printf("第%d个人的密码是: ",i+2); scanf("%d",&s->word); s->num=i+2; } p->next=h; returnh; } voidOrder(Node*h)//输出结果 { Node*p; p=h; Node*d; while(p->next! =p) { if(m<2) { p=p->next; } else { for(i=1;i { p=p->next; } } d=p->next; m=d->word; printf("%d--",d->num); p->next=d->next;//删除结点 p=p->next; free(d); } printf("%d\n",p->num); } voidmain() { printf("试验名称: 约瑟夫斯问题求解\n"); printf("学号: \n"); printf("姓名: xx\n"); printf("=========================================================\n"); time_trawtime1; structtm*timeinfo1; time(&rawtime1); timeinfo1=localtime(&rawtime1); //时间函数; printf("程序运行开始,当前日期和时间: %s",asctime(timeinfo1));printf("请输入总人数: "); scanf("%d",&n); h=CreatList(); printf("请输入初始密码: "); scanf("%d",&m); if(m>n) { printf("初始密码不得大于总人数,请重新输入。 "); scanf("%d",&m); Order(h); } else { Order(h); } time_trawtime2; structtm*timeinfo2; time(&rawtime2); timeinfo2=localtime(&rawtime2); printf("程序运行结束,当前日期和时间: %s",asctime(timeinfo2)); while (1); }
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 实验 报告 约瑟夫 问题 求解