}
函数之间的参数传递:
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<<""<code;
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