3.
约瑟夫退圈问题
:利用
循环链表类
实现约瑟夫退圈问题:
n
个人
(不同
id
)围成一个圈,从
startId(
任意数
)
个开始报数
m(
任意数
)
个
数,数
m
的人出列排成新队列,
m
清零,然后又从下一个人开始数
m
个数开始,数到
m
就出列接在新队列尾部,如此重复,直到所有
人都出列为止,
请输出出列的次序
(依次输出出列人员的编号)。
说明:参数
n
,
stratId
和
m
要通过输入确定,注意要考虑
startId
和
m
大于
n
的情况
代码示例:
#include<iostream>
using namespace std;
//节点类
class Node
{
public:
int id;
Node * next;
Node (int i):id(i),next(nullptr){}
};
//链表类
class List
{
public:
Node * head;
Node * endnode;
List ():head(nullptr){}
void add(int i)//为链表添加一个节点
{
Node * nownode=new Node(i);
if(head==nullptr)
{
head=nownode;
}
else
{
Node * current=head;
while(current->next)
{
current=current->next;
}
current->next=nownode;
endnode=nownode;
}
}
void printlist()//输出链表
{
Node * current=head;
while(current)
cout<<current->id<<" ";
cout<<endl;
}
};
void display(int n,int start,int m)
{
//先创建一个循环链表,记录下每个人的id
List list1;
cout<<"输入从第一个人到最后一个人的id:";
for(int i=0;i<n;i++)
{
int x;
cin>>x;
list1.add(x);
}
list1.endnode->next=list1.head;//尾结点的指针指向头结点,形成一个循环
//开始循环报数
//List list2;//报到m的人重新站成一个新的队列
Node * current=list1.endnode;
while(1)
{
Node * temp=current->next;
if(temp->id==start) break;
current=current->next;
}
//temp指向了start
int count=0;
while(current->next!=current)//如果current为空,说明全部退圈
{
Node * temp=current->next;
++count;
if(count==m)
{
cout<<temp->id<<" ";
current->next=temp->next;
delete temp;
count=0;
}
else current=current->next;
}
cout<<current->id<<endl;
}
int main()
{
int n,start,m;
cout<<"请输入人数:";
cin>>n;
cout<<"从第几个人开始报数(id):";
cin>>start;
cout<<"报数到几时退出循环:";
cin>>m;
display(n,start,m);
return 0;
}