1. 题目
设编号为1,2,……n的n个人围坐一圈,约定编号为k (1≤k≤n)的人从1开始报数,数到m的那个人出列。它的下一位继续从1开始报数,数到m的人出列,依次类推,最后剩下一个为猴王。
2. 解题举例
- 编号 为k者 ,开始前指定
- 每个人 编号 从1 开始
- 数到m 的那个人 被杀
- 被杀死者的下个人 从1 报数
刚开始如下:
假设n=6总共6人,k=1从第一个人开始,m=5,每次从1数到5。
第一轮报数后如下:
从1号开始,数5个数,数完5个数,5号被杀死,第一轮报数后,剩余人数如下。
第二轮报数后,如下:
从6开始报号1,然后4出局,下个人为6。
第三轮报数后,如下:
第四轮报数后,如下:
第五轮报数后,如下:
3. 代码
#include <stdio.h>
#include <stdlib.h>
typedef struct LinkListNode
{
int data;
struct LinkListNode *next;
} LLN, *LL;
int main(int argc, const char *argv[])
{
LL H = NULL; // 无头链表的头指针
LL PDel = NULL; // 用于指向被删除节点
LL PTail = NULL; // 永远指向当前链表的尾
LL PNew = NULL; // 永远指向新创建的节点
int i;
int all_num = 6; // 猴子总数
int start_num = 1; // 从几号猴子开始数
int kill_num = 5; // 数到几杀死猴
// 1.创建出一个单向循环链表
//(1)创建有 all_num 个节点的 无头 单向链表
H = (LL)malloc(sizeof(LLN));
if (NULL == H)
{
perror("H malloc failed");
return -1;
}
H->data = 1; //规定编号从1开始
H->next = NULL; //初始化空指针域
PTail = H; // 尾指针指向当前的第一个结点
// 顺序创建到规定数目的 结点
for (i = 2; i <= all_num; i++)
{
// 创建新的节点
PNew = (LL)malloc(sizeof(LLN));
if (NULL == PNew)
{
perror("PNew malloc failed");
return -1;
}
// 将新结点装上数据
PNew->data = i;
PNew->next = NULL;
// 将新结点链接到链表尾
PTail->next = PNew; // 链接到链表的尾
PTail = PNew; // 尾指针继续指向当前链表的尾
}
// 1 2 3 4 5 6
//(2)将 头结点 保存到 链表的尾结点的next指向 形成 无头单向循环 链表
PTail->next = H; // 形成 无头单向循环链表
// 2.开始杀猴子
//(1)将头指针移动到开始猴子的号码处
for (i = 0; i < start_num - 1; i++)
H = H->next;
//(2)循环进行杀猴子
while (H != H->next) // 终止:就剩一个猴子,只有一个节点
{
// 将头指针移动到即将删除节点的前一个节点
// -2 理解为从1开始数的,和被删结点的 前个结点上
for (i = 0; i < kill_num - 2; i++)
H = H->next;
// 指向被删结点
PDel = H->next;
// 跨过删除节点
// H->next = PDel->next;
H->next = H->next->next;
printf("kill is -------------%d\n", PDel->data);
free(PDel);
PDel = NULL;
// 杀死猴子后,从被杀死结点 的下一个节点 开始继续数,
// 即将头指针移动到开始数的地方
H = H->next;
}
printf("king is=================== %d\n", H->data);
return 0;
}