/*约瑟夫环问题:把n个人的编号依次存放到一个顺序表s1中,从编号k开始数,数到m的人出列,则把出列的人的编号从s1中删除,并把其编号加到(插入)另一个顺序表s2中,最后把s2中的元素依次输出,则可得到依次出列的编号。
*/
#include<iostream>
using namespace std;
const int MaxSize=100;
template<class T>
class SeqList{
private:
T data[MaxSize];
int length; //线性表的长度
public:
SeqList(){length=0;} //建一个空表
SeqList(int n);
~SeqList(){}
int getLength(){return length;} //获取线性表的长度
T getData(int i); //按序号查找第i个元素
void locate(T x); //按值查找元素序号
void insert(int i,T x); //在第i个位置插入值为x的元素
int Delete(int i); //删除线性表中的第i个元素
void printList(); //遍历操作,按序号依次输出各元素
};
//成员函数
template<class T>
SeqList<T>::SeqList(int n){ //带参构造函数,建一个长度为n的顺序表
if(n>MaxSize) throw"参数非法!\n";
for(int i=0;i<n;i++) data[i]=i+1;
length=n;
}
template<class T>
void SeqList<T>::insert(int i,T x){ //在第i个位置插入值为x的元素
if(length>=MaxSize) throw"上溢!\n";
if(i<1||i>length+1) throw"\t\t插入位置非法!\n";
for(int j=length;j>=i;j--){
data[j]=data[j-1];
}
data[i-1]=x;
length++;
}
template<class T>
int SeqList<T>::Delete(int i){ //删除线性表中的第i个元素
if(length==0) throw"\n\t\t这是一个空表!\n";
if(i<1||i>length) throw"\n\t\t查找位置非法!\n";
int x=data[i-1];
for(int j=i;j<length;j++){
data[j-1]=data[j];
}
length--;
return x;
}
template<class T>
void SeqList<T>::printList(){ //遍历操作,按序号依次输出各元素
cout<<"\t\t序号\t出列的编号\n";
for(int i=0;i<length;i++){
cout<<"\t\t "<<i+1<<"\t "<<data[i]<<"\n";
}
cout<<endl;
}
int main(){
try{
int n,k,m;
cout<<"请输入人数:";cin>>n;
SeqList<int> s1(n); //把n个人的编号按顺序存放到s1的顺序表中
cout<<"请输入开始报数的编号:";cin>>k;
if(k<1||k>s1.getLength()) throw"\t\t报数编号非法!\n";
cout<<"请输入数到要出列的数:";cin>>m; //报到m这个数的人(编号)出列
SeqList<int> s2; //s2用来记录依次出列的人的编号
for(int i=0;i<n;i++){
if((s1.getLength()-k)>=(m-1)){ //
k=k+(m-1); //数到m的人其在顺序表对应的位置序号赋给k
s2.insert(i+1,s1.Delete(k)); //数到m的人出列,则把k的元素加给s2的顺序表中
}else{
for(int j=1;j<m;j++){ //因为在k开始数,k只需加(m-1)次,故j取1
if(k<s1.getLength()) k++;
else k=1; //从头循环着数
}
s2.insert(i+1,s1.Delete(k));//输出依次出列的编号
}
}
s2.printList();
}catch(char *p){
cout<<p;
}
return 0;
}