以下是使用循环链表解决Josephus环问题的方法,已加注释。便于理解。
#include <iostream>
using namespace std;
typedef struct LNode{
int data;
LNode *link;
}LNode,*LinkList;
void Josephus(int n,int k,int m)
//n为总人数,k为第一个开始报数的人,m为出列者喊到的数
{
LinkList p,r,curr; //p为当前节点,r为辅助节点,指向P的前驱节点,list为头节点,
//建立循环链表
p = new LNode;
p->data = 0;
p->link = p;
curr = p;
for (int i = 1;i<n;i++)
{
LinkList t = new LNode;
t->data = i;
t->link = curr->link; //第一次进来,curr->link指向自己(头节点);表明t->link指向头节点
curr->link = t; //curr->link指向t
curr = t; //t作为当前节点
}
r = curr;
while (k--)
{
r = p; //r移动到第一个报数的人
p = p->link;
}
while (n--) //最终n减到0 全部踢出约瑟夫环
{
for (int s = m-1;s--;) //根据m的数值来确定向前跳几个节点。m==1 ,则不执行这段代码
{
r = p;
p = p->link;
}
r->link = p->link;
cout<<p->data<<"->";
delete p;
p = r->link;
}
}
int main()
{
Josephus(13,4,2);
return 0;
}
附上在别人博客看到的一种思路:
#include <iostream>
using namespace std;
int main()//约瑟夫环
{
int n=9, m=5,k=2;//n是人数(编号1,2,……,x),m是出列号,k是起始人编号
int j=0, l=0;
int a[10];
for (int i=1;i<=9;i++)
{
a[i]=1;
}
while (l<n)
{
for (int i=1;i<=n;i++)
{
if (a[i]==1)
{
j++;
if (j==m)
{//满足出列号
a[i]=0;
if (i==n&&k>1)
{
cout<<1<<endl;
}
else
{
cout<<i+(k-1)<<endl;
}
j=0;
l++;
}
}
}
}
}