代码
#include <stdio.h>
int main()
{
int n, m; //猴子个数,报数到m退出
int number;//记录猴子实际个数
int count;//为当前循环做准备
int i, pos, prior;//pos>prior
int monkey[301] = { 0 };
int monkey[301] = { 0 };//数组存储下一个猴子的位置,标识为-1的为淘汰
//初始化数组,数组存储下一个猴子的下标
while (~scanf_s("%d%d", &n, &m))
{
if (n == 0 || m == 0)
{
return 0;
}
else
{
for (i = 0; i < n - 1; i++) //初始化数组
{
monkey[i] = i + 1;
}
monkey[i] = 0;//下标为n-1的元素的下个序号为0,形成循环链表
number = n;
pos = 0;
prior = n - 1;
count = 1;
while (number > 1) //淘汰对应间隔元素
{
if (count != m) //不到淘汰位置
{
prior = pos;
pos = monkey[pos]; //数组链表循环时关键步骤
count++;
}
else
{ //更改链接关系
monkey[prior] = monkey[pos];//为以后pos(假指针位移做准备)。
monkey[pos] = -1;//表示淘汰
pos = monkey[prior];//移动到淘汰位置的下一个
//然而prior还是在pos的前一个,只要接下来循环链接过程还是以prior = pos;
/*pos = monkey[pos];
而不是prior++的形式就行。
*/
number--; //
count = 1;
}
错误示范,注意事项
// monkey[prior - 1] = monkey[prior]; //注意关系monkey【prior】里面的值比prior大一,pos同理
// //所以不应该存在 在淘汰循环前一个的赋值。无意义
// monkey[prior] = -1;//淘汰位置出错
// prior = monkey[prior];
// pos = monkey[pos];
// count = 1;
}
printf("%d\n",pos+1);//不能用monkey【pos】,因为可能里面的元素已经被改过了
//monkey[prior] = monkey[pos];
// (改变情况)
}
}
return 0;
}
关于初始化中数组如何模拟循环链表的问题
相当于最后一个元素的monkey【pos】等于第一个元素的pos。
在没有循环删除前 monkey【pos】等于pos+1
monkey【prior】等于prioe+1
循环删除后数组里的元素可能发生错乱。
for (i = 0; i < n - 1; i++) //初始化数组
{
monkey[i] = i + 1;
}
monkey[i] = 0;//下标为n-1的元素的下个序号为0,形成循环链表