问题

[问题描述]
要从n只猴子中选出一位大王。它们决定使用下面的方法:
n只猴子围成一圈,从1到n顺序编号。从第q只猴子开始,从1到m报数,凡报到m的猴子退出竞选,下一次又从退出的那只猴子的下一只开始从1到m报数,直至剩下的最后一只为大王。请问最后哪只猴子被选为大王。

[输入形式]
控制台输入三个整数n,m,q。

[输出形式]
输出最后选为大王的猴子编号。

[样例输入]
7 4 3

[样例输出]
4

算法设计

1、输入n、m、q;
2、建立从1到n编号的循环链表;
3、找到编号为q的节点,设current指向q的前一节点;
4、设计数器i为1,若i<=m:
  4.1 current指向下一个节点;
  4.2 i++;
5、删除current指向的节点;
6、将current指向被删除节点的前一个节点;
若循环链表只剩一个节点,则打印该节点的编号,否则转向第4步。

算法实现

#include <stdio.h>
struct node {
int num;
struct node * next;
};

main()
{
int n,m,q,i;
struct node * head, *tail,* current, *pre;
scanf("%d%d%d",&n,&m,&q);
/*建立循环链表,链表的每个结点记录猴子的编号,head用于记录第一个 猴子,current用于记录新创建的编号节点,tail链表尾部节点。*/
head=NULL;
for(i=1;i<=n;i++)
{
current = (struct node *)malloc(sizeof(struct node));
current->num = i;
current->next = NULL;
if(head==NULL)
head = tail = current;
else
{
tail->next = current;
tail = current;
}
}
current->next = head;
/*找到第q个猴子,current指向第q个猴子,
pre指向第q-1个猴子*/
current = tail;
for(i=1;i<=q;i++)
{
pre = current;
current = current->next;
}

/*若循环链表只剩下一个节点,则找到编号退出循环*/
while( pre->next!=pre )
{
/*从第q个节点,或者从删除的下一个节点开始,从1数到m,
current指向当前所数的节点,
pre指向current的前一个节点。*/
current = pre;
for(i=1;i<=m;i++)
{
pre = current;
current = current->next;
}
/*current指向数到m的节点,删除并释放该节点。*/
pre->next = current->next;
free(current);
}
printf("%d\n",pre->num);

}