约瑟夫环问题:
已知n个人(以编号1,2,3…n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。
采用顺序存储结构中的数组实现。
每次出队了一个人,将这个位置后面的所有数往前移一个位置,将此数覆盖,数组的有效长度也相应的减1
每次出队的人的下标为:
len为每次循环中环的人数,m为数到m的人出队
index=(index+m-1)%len
为什么要取余len?
当m>len时,可以保证出队人的下标总是 >=0 ,<len
C++实现代码:
#include <iostream>
using namespace std;
//将出队的人从数组中删除
int del(int *arr,int index,int &len){
//将出队的那个人从数组中删除(覆盖)
int a=arr[index];
for(int i=index;i<len;i++){
arr[i]=arr[i+1];
}
//数组长度减1
len=len-1;
return a;
}
//寻找出队的人
void josephRing(int *arr,int n,int k,int m){
//第一开始数的人的下标
int index=k-1;
//数组长度
int len=n;
//出环顺序
while(len>1){
//每次出环的人的下标
index=(index+m-1)%len;
//打印输出每次出队人的下标
cout<<del(arr,index,len)<<" ";
}
//剩最后一个人 打印输出
cout<<arr[0]<<endl;
}
int main(){
cout<<"请输入约瑟夫环中的人数:";
int n;
cin>>n;
int *arr=new int[n];
for(int i=0;i<n;i++){
arr[i]=i+1;
}
cout<<"从编号几开始数?:";
int k;
cin>>k;
int m;
cout<<"数到几的出队?:";
cin>>m;
cout<<"出队顺序:";
josephRing(arr,n,k,m);
return 0;
}