问题描述
已知n个人(以编号1,2,3…n分别表示)围坐在一张圆桌周围。从编号1开始报数,数到k的那个人出列;他的下一个人又从1开始报数,数到k的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。
例如n=10,k=3时,输出的出列顺序是3,6,9,2,7,1,8,5,10,4。
程序代码
CLinkList.h
#include<iostream>
using namespace std;
#define MAXSIZE 100
template<class T>
struct Node
{
T data; //数据域
struct Node<T> *next; //指针域,在这里<T>可省略
};
template<class T>
class CLinkList
{
public:
CLinkList(){rear = new Node<T>; rear->next = rear;} //无参构造函数
CLinkList(T a[],int n); //有参构造函数,使用含有n个元素的数组a初始化链表
// ~CLinkList(); //析构函数
void PrintList(); //按次序遍历链表中的各个数据元素
void Delete(int i); //删除链表中第i个元素,并将该元素返回
void Josephus(int i);
private:
Node<T> *rear; //尾指针
Node<T> *front; //头指针
Node<T> *p;
int length;
};
template<class T>
CLinkList<T>::CLinkList(T a[],int n)
{
front = new Node<T>;
Node<T> *r = front;
front->data = a[0]; //此构造函数中头结点也有数据,所以在出环的时候可以不用考虑头结点
length = n;
for(int i=1; i<n; i++)
{
Node<T> *s = new Node<T>;
s->data = a[i];
r->next = s;
r = s;
}
rear = r;
rear->next = front;
}
/*由于在josephus()函数中,已将所有元素删除,所以此处不需要析构函数
template<class T>
CLinkList<T>::~CLinkList()
{
Node<T> *q = front;
while(q)
{
front = q;
q = q->next;
delete front;
}
}
*/
template<class T>
void CLinkList<T>::PrintList()
{
Node<T> *x = front;
for(int i=0; i<length; i++)
{
cout<<" "<<x->data<<" ";
x = x->next;
}
cout<<endl;
}
template<class T>
void CLinkList<T>::Delete(int i)
{
if(i == 0) //如果出环间隔为0
{
Node<T> *q = p;
p = q->next;
cout<<q->data<<" ";
delete q;
length--;
}
else //如果出环间隔不为0
{
for(int x=0; x<i-2; x++) //计算出环位置
{
p=p->next;
}
Node<T> *q = p->next;
p->next = q->next;
p = p->next;
cout<<q->data<<" ";
delete q;
length--;
}
}
template<class T>
void CLinkList<T>::Josephus(int i)
{
p = front;
while(length != 0)
{
Delete(i);
}
}
Josephus.cpp
#include"CLinkList.h"
int main()
{
int n,k,a[MAXSIZE];
cout<<"请输入总数n:"<<endl;
cin>>n;
cout<<"请输入出环间隔k:"<<endl;
cin>>k;
for(int i=0; i<n; i++)
{
a[i]=i+1;
}
CLinkList<int> josephus(a,n);
// josephus.PrintList();
josephus.Josephus(k);
return 0;
}
输出结果
请输入总数n:
20
请输入出环间隔k:
3
3 6 9 12 15 18 1 5 10 14 19 4 11 17 7 16 8 2 13 20
请按 ENTER 或其它命令继续