约瑟夫问题面向对象C++版程序设计报告.docx
- 文档编号:29962526
- 上传时间:2023-08-03
- 格式:DOCX
- 页数:26
- 大小:98.96KB
约瑟夫问题面向对象C++版程序设计报告.docx
《约瑟夫问题面向对象C++版程序设计报告.docx》由会员分享,可在线阅读,更多相关《约瑟夫问题面向对象C++版程序设计报告.docx(26页珍藏版)》请在冰豆网上搜索。
约瑟夫问题面向对象C++版程序设计报告
学院
班级
学号
姓名
摘要
本作业解决Josephus问题的求解,以及Josephus问题的扩展的求解。
Josephus问题的描述如下:
n个小孩围成圈做游戏,游戏将决定出一个胜利者(Josephus问题扩展则可以求出多个获胜者)。
假定一个数m,从第s个小孩起,顺时针计数,每次数到第m个小孩,该小孩离开,接着又从下一个小孩开始数,数到第m个小孩,该小孩也离开,如此不断反复进行,最后剩下的一个(多个)小孩为胜利者。
对于给定的n、m和s,找出最后的胜利者。
Josephus问题的扩展则是在原来Josephus问题基础上增加了“获胜者个数”这一限制。
在本作业中Josephus问题的解决主要是基于对象的解决方案(Object-BasedSolution),其中涉及到BoyRing类和Jose类。
主要实现方式则是环链表,这使得Josephus问题得到一个比较满意的解决。
本作业的程序设计达到了要求,实现的方式相对较好。
最终得到的结果设计者比较满意。
1摘要
1.1设计题目
Josephus问题(JosephusProblem)及其扩展
1.2设计内容
利用循环链表运用面向对象的设计方案实现Josephus问题的求解。
Josephus问题如下:
n个小孩围成圈做游戏,游戏将决定出一个胜利者。
假定一个数m,从第s个小孩起,顺时针计数,每次数到第m个小孩,该小孩离开,接着又从下一个小孩开始数,数到第m个小孩,该小孩也离开,如此不断反复进行,最后剩下的一个小孩为胜利者。
对于给定的n、m和s,找出最后的胜利者。
其中n、m和s都为正整数,切有n>1,1<=m<=n和1<=s<=n的关系。
程序扩展是在Josephus问题的基础上,由原来的1个获胜者扩展到m个胜利者,其实现的方式和Josephus问题的实现基本相同。
其中n、m、s的要求和Josephus问题的完全相同,新增的1<=w<=n。
1.3开发工具
主要用到的开发工具为:
DevC++5.0和Win32。
1.4应用平台
Windows2000/XP/Vista32位
2详细设计
2.1程序结构
改程序分成三个抽象层次,第一层是应用层,直接指使Jose类对象去完成求解工作;第二层是Jose类层,描述Josephus问题的求解细节;第三层是BoyRing类层,辅助Jose类完成求解过程(上述三层间的关系描述如图J-1,这也是程序模块间的关系)。
图J-1.对象实现中程序模块的相互关系
如图J-1所示,main函数用到了Jose类,Jose类又用到了BoyRing类。
整个程序的实现流程如图J-2。
程序中类:
BoyRing类和Jose类
BoyRing类中的数据成员有:
Boy*pBegin,*pivot,*pCurrent三个指针,分别为起始位置的指针,哨兵指针,被切掉位置指针。
BoyRing类中的成员函数分别为:
函数
相关说明
BoyRing(intn);
构造函数。
参数为int类型的n,主要完成空间申请,构造链表,初始化个参数。
VoidcountBy(intm);
用循环的方式数m个小孩,参数为int类型的m
intgetNum()const;
为一个const函数,返回小孩的编号,无参数
voiddisengage();
利用指针实现小孩离队,无参数
voidprintAll()const;
以特定的格式输出小孩的编号,无参数。
本函数在在本程序中没有起任何作用可以去除。
~BoyRing();
析构函数。
释放申请空间,无参数
图J-2.Josephus问题整体程序流程图
Jose类中的数据成员有:
intn,m,s三个int类型的数,分别表示小孩的总数、间隔数、开始数的小孩编号。
Jose类中的成员函数分别为:
函数
相关说明
Jose(intboys,intinterval,intbegin=1);
构造函数,主要功能初始化各个参数,校验输出的m、n、s参数为intboys,intinterval,intbegin=1
voidgetWinner()const;
求胜利者函数,实例化BoyRing类,以特定的格式输出离队小孩的编号和获胜小孩的编号,无参数
主要函数:
BoyRing:
:
BoyRing(intn);
{
if(n<2)throwexception();
pBegin=newBoy[n];
for(inti=1;i<=n;i++)
{
pBegin[i-1].next=&pBegin[i%n];
pBegin[i-1].code=i;
}
pivot=pCurrent=&pBegin[n-1];
}
//图J-3为流程图
图J-3.BoyRing:
:
BoyRing(intn)函数流程图
voidBoyRing:
:
countBy(intm)
{
for(inti=1;i<=m;++i)
{
pivot=pCurrent;
pCurrent=pCurrent->next;
//挪到下一个小孩的位置
}
}
//图J-4为流程图
图J-4.voidBoyRing:
:
countBy(intm)函数流程图
voidJose:
:
getWinner()
const{
cout<<"Thereare"< \n";//输出小孩总个数 BoyRingx(n);//创建环状链表(Boying类对象实例化x) x.countBy(s-1);//转到开始位置 for(inti=1,numinLine=0;i { x.countBy(m); cout<<""< "": "\n"); x.disengage(); } cout<<"\nthewinneris\n"< } 函数之间的参数传递: 1.由主函数依次输入n、m、s三个数的值; 2.主函数调用Jose: : getWinner()函数将n、m、s的值传递到Jose类;同时,Jose类的内部函数Jose: : Jose(intboys,intinterval,intbegin=1)得到传入的参数n、m、s,并对三个数的值进行校验; 3.在voidJose: : getWinner()const函数将n、m、s三个参数通过将BoyRing类实例化成对象实例x,调用x.countBy()函数出入到类BoyRing中。 4.传入BoyRing类中的各个带参数的函数。 2.2主要功能 Josephus问题程序的主要功能是: 通过外界输入3个或(4个)相关参数,在Josephus问题程序成后输出Josephus的的相关结果。 利用循环链表实现Josephus的求解。 Josephus问题如下: n个小孩围成圈做游戏,游戏将决定出一个胜利者。 假定一个数m,从第s个小孩起,顺时针计数,每次数到第m个小孩,该小孩离开,接着又从下一个小孩开始数,数到第m个小孩,该小孩也离开,如此不断反复进行,最后剩下的一个小孩为胜利者。 对于给定的n、m和s,找出最后的胜利者。 其中n、m和s都为正整数,切有n>1,1<=m<=n和1<=s<=n的关系。 Josephus问题主要是利用环链表、指针转向。 其实现如图J-5: 图J-5.Josephus问题中的环链表 算法 Jose类{ 内部数据成员 小孩总数n 开始位置s 计数间隔m 界面 构造函数 求获胜者者函数 } 其中,Jose类界面具有的具体操作描述为: 构造函数 小孩总数校验 开始位置校验 计数间隔数校验 求获胜者函数 输出求解开始,小孩总数 创建环链表(BoyRing类对象) 转到链表开始位置 while(小孩多于1个(w个)) 数m个小孩 小孩输出 小孩离队 endwhile 输出获胜者 在Jose类用到了BoyRing类,其设计如下: BoyRing类{ 内部数据成员 小孩结构指针 当前小孩指针 小孩哨兵指针 界面 构造函数 析构函数 数m个小孩 小孩离队 返回当前小孩编号 输出所有小孩 } 其中,BoyRing类界面的具体操作描述为: 构造函数 按小孩的个数申请空间 初始化环状结构,为小孩编号 指针初始化 析构函数 释放申请空间 数m个小孩函数 for(m间隔) 挪到下一个小孩的位置 endfor 小孩离队函数 哨兵指向的小孩指向当前小孩的的下一个小孩 当前小孩指针赋值与哨兵指针 返回当前小孩的编号 返回当前小孩指针指向的小孩编号 输出所以小孩 按特定的格式输出环中所有小孩的编号 2.3算法实现 //===================================== //boyring.h //===================================== #ifndefHEADER_BOYRING #defineHEADER_BOYRING structBoy { intcode; Boy*next; }; //----------------------------------- classBoyRing { Boy*pBegin,*pivot,*pCurrent; public: BoyRing(intn); voidcountBy(intm); intgetNum()const; voiddisengage(); voidprintAll()const; ~BoyRing(); }; //=================================== #endif//HEADER_BOYRING //===================================== //boyring.cpp //===================================== #include"boyring.h" #include usingnamespacestd; //------------------------------------- //构造函数 //------------------------------------- BoyRing: : BoyRing(intn) { if(n<2)throwexception();//发生错误时自动跳出 pBegin=newBoy[n];//申请一个新的Boy空间,pBegin指向该空间的开始处 for(inti=1;i<=n;i++) { pBegin[i-1].next=&pBegin[i%n];//形成链表 pBegin[i-1].code=i;//给孩子孩子编号 } pivot=pCurrent=&pBegin[n-1];//各指针初始化 } //------------------------------------ //数m个小孩 //------------------------------------ voidBoyRing: : countBy(intm) { for(inti=1;i<=m;++i) { pivot=pCurrent; pCurrent=pCurrent->next;//挪到下一个小孩的位置 } } //------------------------------------ //返回当前小孩编号 //------------------------------------ intBoyRing: : getNum() const{ returnpCurrent->code; } //------------------------------------ //小孩离队 //------------------------------------ voidBoyRing: : disengage() { pivot->next=pCurrent->next;//哨兵指针指向的小孩指向当前小孩的下一个小孩 pCurrent=pivot;//当前小孩指针等于哨兵指针 } //------------------------------------ //输出所有小孩编号 //------------------------------------- voidBoyRing: : printAll()const { intnuminLine=0; Boy*p=pCurrent; do { cout<<""< if(! (++numinLine%10))cout<<"\n";//每一行输出10个 p=p->next; } while(p! =pCurrent); cout<<"\n"; } //------------------------------------ //析构函数 //------------------------------------ BoyRing: : ~BoyRing(){ delete[]pBegin;//释放申请空间 } //------------------------------------ //===================================== //jose.h //===================================== #ifndefHEADER_JOSE #defineHEADER_JOSE classJose{ protected: intn,m,s; public: Jose(intboys,intinterval,intbegin=1); voidgetWinner()const; };//=================================== #endif//HEADER_JOSE //===================================== //jose.cpp //===================================== #include"boyring.h" #include"jose.h" #include usingnamespacestd; //------------------------------------- //构造函数 //------------------------------------- Jose: : Jose(intboys,intinterval,intbegin): n(boys),m(interval),s(begin) { if(n<2||m<1||m>=n||s<1||s>=n)//校验n、m、s { cerr<<"dataerror.\n"; throwexception();//出现错误跳出 } } //------------------------------------ //求获胜者 //------------------------------------ voidJose: : getWinner()const { cout<<"Thereare"< \n";//输出小孩总个数 BoyRingx(n);//创建环状链表(Boying类对象实例化x) x.countBy(s-1);//转到开始位置 for(inti=1,numinLine=0;i { x.countBy(m); cout<<""< "": "\n"); x.disengage(); } cout<<"\nthewinneris\n"< } //------------------------------------ //===================================== //main.cpp //JosephusProblemObject-basedSolving //===================================== #include #include"jose.h" usingnamespacestd; //------------------------------------- intmain(){ cout<<"请依次输入孩子的个数/间隔人数/开始编号: \n"; intn,m,s; cin>>n>>m>>s; Jose(n,m).getWinner(); Jose(n,m,s).getWinner(); } //==================================== 2.4开发日志 推进时间 主要事务 2011年01月01日 问题分析,流程设计,确定项目中各个类,找出各类的之间的联系以及类内部的各个成员。 2011年01月02日 根据分析所得设计实现算法,编写代码,编译、调试程序。 2011年01月03日 项目完成,进行总结。 3程序调试及运行 3.1程序运行结果 Josephus的执行结果 Josephus问题程序执行后输出的结果。 由键盘依次输入小孩总数10、间隔人数3、开始编号3; 程序执行后输出两个结果,第一个结果是Jose(n,m).getWinner()的执行结果,由于在只有n、m两个参数是,其第三个参数默认值设定为1,所以,其结果执行为: Thereare10boys。 Boyleavedinorder: 3692718510 thewinneris4 第二个结果是Jose(n,m,s).getWinner()的执行结果,由于这一3个参数完全,所以,其执行结果为: Thereare10boys。 Boyleavedinorder: 5814931072 thewinneris6 Josephus的扩展程序执行结果 Josephus问题扩展程序执行后输出的结果。 由键盘依次输入小孩总数10、间隔人数3、开始编号3; 程序执行后输出三个结果,第一个结果是Jose(n,m).getWinner()的执行结果,由于在只有n、m两个参数是,其第三个参数默认值设定为1,所以,其结果执行为: Thereare10boys。 Boyleavedinorder: 3692718510 thewinneris4 第二个结果是Jose(n,m,s).getWinner()的执行结果,由于这一3个参数完全,所以,其执行结果为: Thereare10boys。 Boyleavedinorder: 5814931072 thewinneris6 第三个结果是Jose(n,m,s,w).getWinner()的执行结果,由于这次多了一个获胜者人数的参数3,所以,其执行结果为: Thereare10boys。 Boyleavedinorder: 57149310 winners726 3.2程序使用说明 本程序在使用要注意: 1.输入参数时要注意数据的格式为正整数; 2.输入参数的个数Josephus为3(Josephus问题的扩展为4个); 3.输入个参数之间的关系,小孩总数大于等1个;开始位置要大于等于1且小于等小孩总数;计数间隔要大于1且小于小孩总数。 3.3程序开发总结 通过这个学期对面向对象的程序设计的学习,使我本人理解了面向对象的重要性及实用性,同时也锻炼了我们自主学习、查阅资料等方面的能量。 本次程序设计虽然是书上的原程序,整个作业的完成有没有花很多的时间,但我从作业的完成过程中学到了很多东西,它使我明白了独立思考的重要性,动手实践的重要性,看懂了,不代表理解了,会做了。 亲自对手才能发现问题,才知道想办法去解决,而不是理所当然的认为是什么样的。 同时,它也磨练了我们的意志,开发了我们的大脑。 使我们明白什么“叫吃得苦中苦,方为人上人”;明白了成功需要怎样做。 它也教会了我们怎样学习,怎样生活,怎么面对将来的路。 4附件(源程序) //===================================== //boyring.h //===================================== #ifndefHEADER_BOYRING #defineHEADER_BOYRING #include usingnamespacestd; //------------------------------------ structBoy { intcode; Boy*next; }; //----------------------------------- classBoyRing { private: Boy*pBegin,*pivot,*pCurrent; public: BoyRing(intn); voidcountBy(intm); intgetNum()const; voiddisengage(); voidprintAll()const; ~BoyRing(); }; //=================================== #endif//HEADER_BOYRING //------------------------------------- //构造函数 //------------------------------------- BoyRing: : BoyRing(intn) { if(n<2)throwexcep
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 约瑟夫 问题 面向 对象 C+ 程序设计 报告