UU们可能都不知道约瑟夫环的问题,我介绍一下下。
介绍
约琴夫环问题约瑟夫环问题由古罗马史学家约瑟夫提出。他参加并记录了公元66一70年犹太人反抗罗马的起义。约瑟夫作为一个将军,设法守住裘达伯特城达47天之久。在城市沦陷之后,他和40名死硬的将士在附近的一个洞穴置难。在那里,这些起义者表决说”要投降毋宁死”、于是,约瑟夫建议每个人轮流杀死他旁边的人,而这个顺序是由抽签决定的。约瑟夫有预谋地抓到了最后一签,并且,作为洞穴中的两个幸存者之一,他说服了他原先的牺牲品一起投降了罗马。
emmm,就是这样,嘿嘿嘿嘿,开始将题目思路吧。
我们先设人数为5,循环数为3.开始作图:
这需要一个循环的结构,在大一就学习了数组,老是想不出咋循环,用的是计数器,然后靠%的去余数的方法也能做,但是今天我们说一下链式结构咋做。
如果我们使用链表的话,那就得考虑:
-
是否有头结点,毕竟头结点也会进入循环计数范围,所以说,是不需要头结点的。
-
需要几个指针,他们应该在那个位置?我做的是两个指针pre和p,他们一起移动,p负责寻找删除点,pre是在某点删除后把链表连起来的作用。
伪代码
注意初始化,还删除结点时,p指向pre的后继结点
C++代码
我们先看一下题目,按其格式打一下代码,其实无论题目如何说,其实主要问你的是人数和报的数。
我们要做的就是,设结点和三个函数的代码,分别是单链表的析构函数、构造函数、循环函数。
#include
using namespace std;
struct Node{
int data;
Node *next;
};
class Heng
{
public:
Heng(int n);
~Heng( );
void Chi(int m);
private:
Node *rear;
}
构造函数要完成的事情,就是做一个循环单链表,了解这个目的,而且每一个数据域是连续的排到规定人数。按我之前介绍的构造单链表,是有两种方法,头插法和尾插法,每一种方法数据进入单链表的顺序都不一样,但是头插法我不会做,毕竟每有头结点,如果你做出了,我们可以一起讨论。
我真的很想知道用头插法咋设计。
Heng::Heng(int n){
Node *s;
s = NULL;
rear =new Node;
rear->data = 1;
rear->next =rear;
for(int i =2;i<n+1;i++){
s =new Node;
s->data = i;
s->next =rear->next;
rear->next = s;
rear = s;
}
}Heng::Heng(int n){
Node *s;
s = NULL;
rear =new Node;
rear->data = 1;
rear->next =rear;
for(int i =2;i<n+1;i++){
s =new Node;
s->data = i;
s->next =rear->next;
rear->next = s;
rear = s;
}
}
单链表设计完之后,需要做的是做游戏咯。按循环排除人,就需要计数器,count,还有我们之前说的两个工作指针。(count取余数为0,是我用的方法,此段代码是书中代码,讲的比我清楚)就到需要删除的数了。这时候需要pre保存之前p后面next的数据,所以需要两个指针。
Heng::Chi(int m){
Node *pre = rear, *p = rear->next; //初始化工作指针p和pre
int count = 1;
cout << "出环的顺序是:";
while (p->next != p) //循环直到循环链表中只剩一个结点
{
if (count < m) { //计数器未累加到密码值
pre = p; p = p->next; //将工作指针pre和p分别后移
count++;
}
else { //计数器已经累加到密码值
cout << p->data<< " "; //输出出环的编号
pre->next = p->next; //将结点p摘链
delete p;
p = pre->next; //工作指针p后移,但pre不动
count = 1; //计数器从1开始重新计数
}
}
cout << p->data << " "; //输出最后一个结点的编号
delete p; //释放最后一个结点
rear = nullptr;
}
最后一个是析构函数,就是释放空间的作用,我觉着就不用说咯。
一定要写析构函数哦,不然会有报错:
我之前创造类的时候,如果你细心,你会发现我在后面没有打“;”,这个也会报错哦!
完整代码(和上面有些不同):
#include <iostream>
using namespace std;
struct Node
{
int data;
Node *next;
};
class Heng
{
public:
Heng(int n)
{
Node *s = NULL;
rear = new Node;
rear->data = 1; rear->next = rear;
for (int i = 2; i <= n; i++)
{
s = new Node; s->data = i;
s->next = rear->next;
rear->next = s;
rear = s;
}
}
void Chi(int m)
{
Node *a = rear, *b = rear->next;
int num = 1;
while (b->next != b)
{
if (num % m!=0) { //之前这打错了,抱歉哈。
a = b; b = b->next;
num++;
}
else {
cout << b->data<< " ";
a->next = b->next;
delete b;
b = a->next;
num ++;
}
}
cout << b->data << " ";
delete b;
rear = NULL;
}
~Heng( )
{
if (rear != NULL){
Node *p = rear->next;
while(rear->next != rear)
{
rear->next = p->next;
delete p;
p = rear->next;
}
delete rear;
}
}
private:
Node *rear;
};
int main( )
{
int x, y;
cin >> x;
cin >> y;
Heng R(x);
R.Chi(y);
return 0;
}
OK,这次分享结束咯。
今天补一个错误,之前打代码没有注意,吧声明的num打错成count,现在改动了,感谢粉丝指正。大家一起加油(σ゚∀゚)σ..:*☆。