#include <stdio.h>
#include <stdlib.h>
typedef struct node_t
{
int data;
struct node_t* next;
}link_node_t;
int main(int argc, const char *argv[])
{
int all_num = 7;//代表猴子的总数
int start_mum = 3;//从3号猴子报数
int kill_num = 4;//数到几杀死猴子
int i;
printf("请您输入猴子的总数 起始号码 数到几出局:\n");
scanf("%d%d%d",&all_num,&start_mum,&kill_num);
//1. 创建一个无头的单向链表,数据域装上1-all_num的猴子编号
link_node_t* phead = malloc(sizeof(link_node_t));
if(phead == NULL)
{
printf("malloc failed!!\n");
return -1;
}
phead->data = 1;//赋值为1,代表1号猴子
phead->next = NULL;
//2.剩余的2-all_num猴子的编号,我们用尾插法,插入在链表的尾巴
link_node_t* ptail = phead;//最开始链表只有一个节点,既是头节点又是尾节点
for(i = 2; i <= all_num; i++)//用i代表2-all_num每一个猴子的编号
{
//每循环一次,就申请一个结构体空间,数据域来保存猴子的编号
link_node_t* pnew = malloc(sizeof(link_node_t));
if(pnew == NULL)
{
printf("malloc failed!!\n");
return -1;
}
pnew->data = i;//猴子编号赋值
pnew->next = NULL;
ptail->next = pnew;//将新节点插入在尾巴上
ptail = pnew;//ptail = ptail->next; 插入之后表变长,尾指针向后移动一个位置,继续指向当前的尾巴
}
//让上面的无头单向链表形成一个单向循环链表,形成一个环
ptail->next = phead;
#if 0
while(1)
{
printf("%d\n",phead->data);
phead = phead->next;
sleep(1);
}
#endif
//在杀猴之前,先将头指针,移动到报数猴子的位置
for(i = 0; i < start_mum-1; i++)
phead = phead->next;
while(phead != phead->next)//phead == phead->next 说明就剩下一个节点了
{
//将头指针移动到删除位置的前一个位置
for(i = 0; i < kill_num-2; i++)
phead = phead->next;
//定义一个pel指向被删除节点
link_node_t* pdel = phead->next;
//跨过被删除节点
phead->next = pdel->next;
//释放被删除节点
printf("kill ---> %d\n",pdel->data);//调试程序,将杀死的猴子号码打印
free(pdel);
//杀死猴子后,我们需要将头指针移动到 报数猴子的位置上,所以
//phead最开始删除位置的前一个位置,所以删除之后,要向后移动一个位置,再开始报数
phead = phead->next;
}
printf("monkey king is %d\n",phead->data);
free(phead);
return 0;
}