#include <iostream>
using namespace std;
struct child
{
int id;
child *nextChild;
child *preChild;
};
class Game
{
private:
int sum;
int k;
child first;
public:
Game(int sum,int k)
{
this->sum = sum;
this->k = k;
first.id = 1;
}
void createCycleLink()
{
child temp = first;
int num = 2;
while(num!=sum)
{
child node;
node.id = num++;
temp.nextChild = &node;
node.preChild = &temp;
temp = node;
}
child node;
node.id = sum;
first.preChild = &node;
node.nextChild = &first;
}
void gameStart()
{
child temp = first;
while(sum!=1)
{
int count = 1;
while(count<k)
{
count++;
temp = *temp.nextChild;
}
child kill = temp;
child kill_next = *kill.nextChild;
child kill_pre = *kill.preChild;
kill_next.preChild = &kill_pre;
kill_pre.nextChild = &kill_next;
cout<<kill.id<<" ";
temp = kill_next;
sum--;
}
cout<<endl<<temp.id<<endl;
}
};
int main()
{
Game game(10,1);
game.createCycleLink();
game.gameStart();
return 0;
}
上面的代码是错误的,我用struct构造双向循环链表,有问题。
其实约瑟夫问题根本就是不需要构建双向循环链表的,只是需要单向循环链表就行了。
#include<cstdio>
#include<cstdlib>
struct Jonse
{
int code;
Jonse *next;
};
Jonse *createCycleLink(int sum)
{
Jonse *head,*p;
int i;
head = (Jonse *)malloc(sizeof(Jonse));
p = head;
for(i=1;i<=sum;i++)
{
p->code = i;
if(i<sum)
{
p->next = (Jonse*)malloc(sizeof(Jonse));
p = p->next;
}
}
//p->code = sum;
p->next = head;
return head;
}
Jonse *gameStart(Jonse *head,int m)
{
//q 一直指向p的前一个节点
Jonse *p,*q;
p = head;
while(p!=p->next)
{
for(int i=1;i<m;i++)
{
q = p;
p= p->next;
}
printf("%d\t",p->code);
//重新构造循环链表
q->next = p->next;
//释放p节点
free(p);
p = NULL;
//从下一个节点重新开始
p = q->next;
}
printf("\nThe winner is %d\n",p->code);
return head;
}
void showList(Jonse *head)
{
Jonse *p;
p = head;
do
{
printf("%d\t",p->code);
p = p->next;
}while(p!=head);
}
int main()
{
Jonse *head = createCycleLink(10);
gameStart(head,2);
//showList(head);
return 0;
}
上面的约瑟夫问题代码可以说是很优美的了
总之约瑟夫就会一个单向循环链表的问题 注意建表的细节并且在遍历的时候注意保存前面的节点 还有清除节点的过程