1.三种解法的异同
如果说前两种方法功能相同,实现方法不同,是因为在数据的存储结构上,第一种方法是采用了一维动态数组,第二种方法是采用了单循环链表存储结构,致使尽管最后执行结果是相同的,但写出的语句代码却是有很大的差别,但是前两者的共同点是都属于面向过程的编程方法。
第三种约瑟夫环的解法,除了存储结构不同,因为这种方法在内存中申请连续的空间,有多少个小朋友,就申请了多少个数据结点的连续空间,但每个数据的后继结点是由每个结点的指针域来描述的,是在连续空间上的链式存储,因此说存储结构上是不同的。另外,在编程方式上也与前两种方法不一样,这种方法是面向对象的编程方法。
C++语言之所以让学生感到复杂,是因为它有四种编程范式,分别为 面向过程、 面向对象、 泛型编程和函数编程(Lambda 表达式实现),属于技术覆盖非常全面的一种编程语言。
2.两个类的设计
面向对象的编程方法,类的设计如下:
小孩结构体
{
小孩编号
后面小孩的地址
}
小孩的循环链队类(ChiledredRingLink)——约瑟夫环
{
数据成员:
链队队头指针
当前小孩指针
当前小孩前一个小孩的指针(因为当前小孩出队,需要前一个小孩的地址)
函数:
构造函数
{
按小孩个数申请空间
把所有的小孩初始化为一个单循环链队
给三个数据成员赋值
}
析构函数 { 释放构造函数申请的空间 }
当前指针指向到指定位置m的指针移动函数
{
for (i=1;i<m;i++)
当前数据指针和它的前驱指针两个指针一起移动
}
小孩出队函数 { 让当前指针的前驱指针,指向当前指针下一个小孩 当前指针后移一个 }
获取当前小孩编号的函数
{ 返回当前指针的数据域的值,这个值是小孩的序号
}
输出所有小孩
{
按每行6个小孩,输出所有的孩子
}
}
循环链队应用类
{ 数据成员:
小孩人数
间隔值
开始位置
函数:
构造函数
{
数据有效性验证
对3个数据成员赋值
}
查找胜利者函数
{
创建一个循环链队
当前指针指向起始位置
for(int i=1;i<小孩个数;i++)
{ 到指定间隔值位置
输出离队小孩序号
小孩离队
}
最后队列中的一个小孩儿是胜利者
}
3.实现代码
#include <iostream>
using namespace std;
struct Child{
int data; // 小孩儿序号
Child *next; //指向下一个小孩儿的指针
};//小孩儿的结构定义
class ChildRingLink
{
public:
ChildRingLink(int n)//构造函数 n个小孩儿的循环链表
{
if(n<2) throw exception();
pHead=new Child[n];//申请了一个数组,数组中每个元素是Child结构体类型
for(int i=1;i<=n;i++){
pHead[i-1].next=&pHead