n个孩子围成一圈,给他们编号1~n,从1号开始报数,数到m的孩子出去,然后继续出去的下一个孩子报数,求最后剩下的孩子的编号
本程序用的有头结点的循环链表实现的,大家可以用无头结点的循环链表来实现或用求模的方法实现。
代码如下:
//约瑟夫问题
#include <iostream>
using namespace std;
template<class T>
struct Node
{
T data;
Node<T> * next;
};
template<class T>
class CirList
{
private :
Node<T> * first,*rear,*cur;
public :
CirList()
{
first = new Node<T>;
first->next = NULL;
rear->next = rear = first;
cur = first;
}
~CirList()
{
delete first;
}
void Add(T x)//采用尾差法构建循环链表
{
Node<T> * s = new Node<T>;
Node<T> * p = rear->next;
s->data = x;
rear->next = s;
s->next = p;
rear = s;
}
void move(int num)//移动num次
{
for (int i = 0; i < num; i++)
{
if (i && cur == first)//考虑特殊情况
{
i--;
}
cur = cur->next;
}
}
void del()
{
Node<T> * p = cur->next;
if (p == first)//考虑特殊情况
{
p = p->next;
first->next = p->next;
}
else
{
cur->next = p->next;
}
delete p;
}
T GetFinal()
{
T temp = first->next->data;
delete first->next;
return temp;
}
};
int main()
{
CirList<int> list;
int n,m,i,j;
printf("Input n,m: ");
scanf("%d %d",&n,&m);
for (i = 1; i <= n; i++ )
{
list.Add(i);
}
for (j = 0 ; j < n - 1; j++)//一共要删除n-1个
{
list.move(m - 1);//移到报数为m的前一个人
list.del();//删除报数为m的人
}
cout<<list.GetFinal()<<endl;
return 0;
}