约瑟夫环.docx
- 文档编号:26869707
- 上传时间:2023-06-23
- 格式:DOCX
- 页数:15
- 大小:556.42KB
约瑟夫环.docx
《约瑟夫环.docx》由会员分享,可在线阅读,更多相关《约瑟夫环.docx(15页珍藏版)》请在冰豆网上搜索。
约瑟夫环
目录
摘要1
前言2
正文3
1.问题描述3
2.逻辑设计3
3.详细设计5
4.程序编码6
5.程序调试与测试8
6.结果分析8
7.软件安装和使用说明书12
设计总结14
参考文献15
致谢16
摘要
约瑟夫环问题是典型的线性表的应用实例,其开发主要包括后台数据库的建立和维护以及前端应用程序的开发两个方面。
对于前者要求建立起数据一致性和完整性强、数据安全性好的库。
而对于后者则要求应用程序功能完备,易使用等特点。
经过分析,我们使用MICROSOFT公司的MicrosoftVisualC++6.0开发工具,利用其提供的各种面向对象的开发工具,尤其是数据窗口这一能方便而简洁操纵数据库的智能化对象,首先在短时间内建立系统应用原型,然后,对初始原型系统进行需求迭代,不断修正和改进,直到形成用户满意的可行系统。
关键词:
单循环链表;c语言;约瑟夫环;
前言
数据结构是研究数据元素之间的逻辑关系的一门课程,以及数据元素及其关系在计算机中的存储表示和对这些数据所施加的运算。
该课程设计的目的是通过课程设计的综合训练,培养分析和编程等实际动手能力,系统掌握数据结构这门课程的主要内容。
本次课程设计的内容是用单循环链表模拟约瑟夫环问题,循环链表是一种首尾相接链表,其特点是无须增加存储容量,仅对表的链接方式稍作改变,使表处理更加灵活,约瑟夫环问题就是用单循环链表处理的一个实际应用。
通过这个设计实例,了解单链表和单循环链表的相同与不同之处,进一步加深对链表结构类型及链表操作的理解。
通过该课程设计,能运用所学知识,能上机解决一些实际问题,了解并初步掌握设计、实现较大程序的完整过程,包括系统分析、编码设计、系统集成、以及调试分析,熟练掌握数据结构的选择、设计、实现以及操作方法,为进一步的应用开发打好基础
正文
1.问题描述
约瑟夫环问题描述的是:
设编号为1,2,…,n的n(n>0)个人按顺时针方向围坐一圈,每个人持有一正整数密码。
开始时选择一个正整数作为报数上限m,从第一个人开始顺时针方向自1起顺序报数,报到m时停止报数,报m的人出圈,将他的密码作为新的m值,从他在顺时针方向上的下一个人起重新从1报数。
如此下去,直到所有人都出圈为止。
令n最大值为100。
要求设计一个程序模拟此过程,求出出圈的编号序列。
2.逻辑设计
1、循环链表抽象数据类型定义
typedefstructLNode//定义单循环链表中节点的结构
{
intnum;//编号
intpwd;//password
structLNode*next;//指向下一结点的指针
}LNode;
2、本程序包含一下几个模块
(1)构造结点模块
LNode*createNode(intm_num,intm_pwd)
{
LNode*p;
p=(LNode*)malloc(sizeof(LNode));//生成一个结点
p->num=m_num;//把实参赋给相应的数据域
p->pwd=m_pwd;
p->next=NULL;//指针域为空
returnp;
}
(2)创建链表模块
voidcreateList(LNode*ppHead,intn)
(3)出队处理模块
voidjose(LNode*ppHead,intm_pwd)
(4)约瑟夫环说明输出模块
voidinstruction()
(5)菜单模块
voidmenu()
(6)主函数模块
intmain()
函数的调用关系图如下:
3.详细设计
是一个采用单循环链表,另一个采用双向循环链表来解决问题。
第一步是定义结构变量结点linklist,并在该结点下定义结点的元素域:
data,password,指针域:
lLink和rLink。
然后建立一个由n个链结点,无表头结点的双向循环链表。
并由构造函数对结点赋值,由随机函数rand()产生每个结点的password。
由于每个结点的password是由随机函数产生的,也就是每个结点的password是后知的,所以在一开始人为地指定一个结点的顺序,由此结点开始报数。
报password个数后,报到的那个结点被删除,它的password被记录下,由它的下一个结点开始逆方向报数………如此循环,直到循环链表里只剩下一个结点,那就是问题所求的结果。
具体到问题上,还需要创建一个Joseph类,由构造函数来初始化,输入所有的人数,也就是表长,然后指定由第几个人开始报数。
在Joseph类中定义一个GetWinner()函数,由它来实现获得最后的胜利者。
并在该类中设置一个判断语句来确定先由顺时针报数并淘汰了一个人之后,再按逆时针顺序报数,如此交替进行。
链表都是由一个个结点组成,由于结点的不同,组成的链表也不同。
因此需要创建双向链表结点。
由于每一个结点有一个密码和一个序号,所以可以将结点结构体定义为:
password
data
rLink
llink
structNode{
intdata;
intpassword;
DNode*llink;
DNode*rlink;}
创建一个空双向循环链表,双向循环链表和每个结点包括三个域:
Element,
lLink,rLink.其中element为元素域,rLink域为指向后继结点的指针,新增的lLink域用以指向前驱结点。
双向链表也可以带表头结点,并且也可以构成双向循环链表。
此时,表头结点的rLink,lLink分别指向双向循环链表的头结点(或表头结点)和尾结点。
一个结点的lLink域的指针指向它左边结点的后部,这并不意味着该结点的lLink域保存的仍是该左边结点存储块的起始地址。
在此处,指针指向某个结点任何部分都是等价的,都是指该存储块的起始位置.
4.程序编码
//Joseph问题求解算法的设计与实现
#include
#include
structlist
{
intnum,code;
structlist*next;
};
voidmain()
{
printf("Joseph问题求解算法的设计与实现\n\n");
inti,j,m=1;
intkey;//密码.
intn;//人数.
list*p,*s,*head;
head=(list*)malloc(sizeof(list));//为头结点分配空间.
p=head;
printf("输入人的总个数:
");
scanf("%d",&n);
for(i=1;i<=n;i++)
{key=rand()%100;
printf("第%d个人的密码:
%d\n",i,key);
s=p;
p=(list*)malloc(sizeof(list));//创建新的结点.
s->next=p;
p->num=i;
p->code=key;
}
p->next=head->next;
p=head;
head=head->next;
free(p);//释放头结点.
p=head;
do{
printf("\n第%d号成员的密码为:
%d",p->num,p->code);//输出链表.
p=p->next;
}while(p!
=head);
printf("\n\n输入第一个报的数:
\n");
scanf("%d",&key);
printf("\n出列顺序为:
\n");
do
{j=1;p=head;
while(j s=p; p=p->next; j++; }//报数过程. i=p->num; key=p->code; printf("%d: 第%d号成员出列\n",m,i); m++; s->next=p->next; head=p->next;//重新定义head,下次循环的开始结点. free(p);//释放已出列的结点. n--;//人数减一. }while(n>0); } 。 5.程序调试与测试 调试过程中,曾出现过缺少分号、括号之类的错误,还出现过运算顺序颠倒,致使运算出现了错误,在经过仔细的检查并且向人请教,终于得出了正确结果. 6.结果分析 进入界面输入总个数7,产生随机密码,输入第一个报的数8,出列顺序为 1,6,4,5,3,2,7. 输入总个数9,随机产生9个密码为41,67,34,0,69,24,78,58,62,输入第一个报的数为6,则出列顺序为,6,5,3,9,2,8,1,4,7。 输入总个数6,产生密码给这六个编号,输入第一个报的数为20,则产生出列顺序为2,4,5,3,1,6. 输入总个数5产生随机密码,再输入第一个报的数是5,产生出列顺序5,1,3,2,4. 输入总个数3产生随机密码,第一个报的数为7,则出列顺序为1,2,3. 7.软件安装和使用说明书 此程序可在VC++6.0中实现。 进入程序窗口,提示输入人的总个数。 随便输入一个数N,对应则为1号,2号,3号…….N号,确定了在程序运行的过程中的总人数,程序随机产生与人数像对应的密码M个数分配给每个人,人为随机输入第一个所报的数,确定为第一次报数的上限,然后程序自行计算出这N个人得出列顺序。 图1,随便输入一个数N。 为输入人的总个数。 图2。 输入一个数4,随机产生4个密码41,67,34,0。 再输入一个数作为第一个报的数。 图3。 输入20作为第一个报的数,产生出列顺序4,1,2,3。 设计总结 为期两周的课程设计快结束了,通过这次数据结构课程设计,我感受最深的就是对于循环链表的使用,可以说对循环链表有了比以前更进一步的认识,以前只是一知半解的,如果只给个题目自己根本不能把程序完整地编写出来,所以这次课程设计最大的收获就在于对循环链表有了一定的理解,包括其中的一系列操作,如建立一个循环链表,删除链表中的一个结点,增加一个结点等。 在这次课程设计过程中需要我们一边设计一边探索,这这个过程当中我发现自己在数据结构方面知识掌握不够深入,对一些基本概念不能很好的理解,对一些数据结构不能够熟练的进行上机实现,这是自己比较薄弱的。 学好基础知识是理论付诸实践的前提,这样理论和实践才能充分地结合起来。 在以后的学习中,我还要努力改正,充分利用上机实验的机会提高自己。 在程序的输入的时候,因为自己对键盘的不熟练,代码又很多很繁琐,常常会产生放弃的念头,从中我也感受到只有坚持到底,胜利才会出现。 在调试程序的时候我也有所体会,虽然约瑟夫环问题不是很难,但调试的时候还是会出现很多错误,因此我们不能认为容易就不认真对待。 在以后的学习中,要能不断发现问题,提出问题,解决问题,从不足之处出发,在不断学习中提高自己。 参考文献 1张乃孝,裘宗燕.数据结构C++与面向对象的途径.北京: 高等教育出版社,1998 2周云静.数据结构习题解析与上机指导.北京: 冶金工业出版社,2004 3陈慧南.数据结构—C++语言描述.北京: 人民邮电出版社,2005 4严蔚敏,吴伟民.数据结构.北京: 清华大学出版社,1997 5AdamDrozdek.数据结构与算法.北京: 清华大学出版社,2006 6徐孝凯.数据结构实验.北京: 中央广播电视大学出版社,2001 致谢 我的这次数据结构课程设计的题目是: 《约瑟夫环》,通过对该题目的设计,我加深了对数据结构及存储结构的理解,进一步地理解和掌握了课本中所学的各种数据结构,尤其是对单循环链表上基本运算的实现,学会了如何把学到的知识用于解决实际问题,锻炼了自己动手的能力。 通过这次数据结构课程设计,我感受最深的就是对于循环链表的使用,可以说对循环链表有了比以前更进一步的认识,以前只是一知半解的,如果只给个题目自己根本不能把程序完整地编写出来,所以这次课程设计最大的收获就在于对循环链表有了一定的理解,包括其中的一系列操作,如建立一个循环链表,删除链表中的一个结点,增加一个结点等。 在调试程序的时候我也有所体会,虽然约瑟夫环问题不是很难,但调试的时候还是会出现很多错误,因此我们不能认为容易就不认真对待。 在以后的学习中,要能不断发现问题,提出问题,解决问题,从不足之处出发,在不断学习中提高自己。 两周的课程设计很短暂,但其间的内容是很充实的,在其中我学习到了很多平时书本中无法学到的东西,积累了经验,锻炼了自己分析问题,解决问题的能力,并学会了如何将所学的各课知识融会,组织起来进行学习,总而言之这两周中我学到很多,受益匪浅。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 约瑟夫