题目描述
设有 n 个人围坐在圆桌周围,现从某个位置 k 上的人开始报数,报数到 mm的人就站出来。下一个人,即原来的第 m+1个位置上的人,又从 1 开始报数,再报数到 m 的人站出来。依次重复下去,直到全部的人都站出来为止。试设计一个程序求出这 n 个人的出列顺序。
要求一:采用循环链表解决。
要求二:可以使用模拟法,模拟循环链表。
要求三:可以不使用循环链表类的定义使用方式。
输入描述
输入只有一行且为用空格隔开的三个正整数 n,k,m,其含义如上所述。
输出描述
共 n行,表示这 n 个人的出列顺序。
输入输出样例
输入
3 5 8
输出
3
2
1
这道题的话用c写一个双链表实现就可以,思路是几个循环,第一个循环找到初始报数的位置,第二个循环里进行报数,出人,结束条件是链表中只剩下最后一个元素,最后循环结束再将最后一个元素输出,注意控制好循环的量即可。
#include <iostream>
using namespace std;
struct Node
{
int data;
Node *pNext;
};
int main()
{
int n, k, m, i; //n个人从k位置开始报数,数到m出列
Node *p, *q, *head;
cin >> n >> k >> m;
//初始化链表
Node * first = (Node *)new Node;
p = first;
first->data = 1;
for (i = 2; i <= n; i++)
{
q = new Node;
q->data = i;
p->pNext = q;
p = p->pNext;
}
p->pNext = first;
p = first; //形成循环链表
for (i = 1; i <= k - 1; i++) //找到第k个位置的那个人,即初始位
p = p->pNext;
while (p != p->pNext) //只剩下一个结点的时候停止(剩下一个结点时头尾一致)
{
for (i = 1; i < m - 1; i++) //开始报数,循环结束时 p为第m-1个
{
p = p->pNext;
}
//所以q为第m个,出列
q = p->pNext; //q为要出队的元素
cout << q->data << endl;
p->pNext = q->pNext;
delete q;
p = p->pNext; //从第m+1个开始重新报数
}
cout << p->data << endl; //循环结束,只剩最后一个元素,输出
return 0;
}
起初我想用list容器去写,也很方便,但是思路没有这么简单明了,下面贴出我用list容器实现的算法,需要注意的点是利用迭代器在遍历的时候,要注意界限,包括最后那里要记得多用一个迭代器来判断下位置是否是最后一个,否则会乱了。
#include <iostream>
using namespace std;
#include <list>
list<int> l1;
int main()
{
int n,k,m;
int i=1;
cin >> n >> k >> m;
//循环链表初始化
for(i=1;i<=n;i++)
{
l1.push_back(i);
}
//找到起始位置k的那个人
list<int>::iterator it=l1.begin();
for(int j=1;j<k;j++)
{
it++;
if(it==l1.end())
{
it=l1.begin();
}
}
//开始报数 用两个循环 外层循环为总共链表中的个数,内层循环为每一次报数淘汰过程
for(int l=1;l<n;l++)
{
for(int j=1;j<m;j++)
{
it++;
if(it==l1.end())
{
it=l1.begin();
}
}
cout<< (*it)<<endl;
//多加一个判断,防止这个数是在末尾
list<int>::iterator it_1 = it;
it_1++;
if(it_1==l1.end())
{
l1.erase(it);
it=l1.begin();
}else{
it=l1.erase(it); //erase返回值是删除位置的下一个位置,刚好就是从这里继续开始报数,不过要多加一个判断,万一这个位置在末尾
}
}
cout<< l1.back() <<endl;
// 请在此输入您的代码
return 0;
}
好像遍历还可以用其他的函数来实现,但是自己还不是非常熟悉,待我去网上再学习一番,有后续再更更,也欢迎大家评论指点