这是一个经典的问题,内容是click here。本文章要实现的是:一共n个人,从第k个人开始报数,数到m的淘汰。从他的下一个人接着数,直到剩余一个人为止。
首先,生成n个人的单链表,并从第k个人开始生成。
首尾相接后,如图:
第一个节点数据元素存的是k,也就是说从第1个开始数到m,
此时q指向m-1,p指向第m个元素。将第p个元素删除即可,然后循环遍历,知道最后一个人剩下。
思路就是这样。
编译环境为Code::Blocks,由于能力有限,难免有bug,仅给读者提供思路。
代码如下:
#include<stdio.h>
#include<string.h>
typedef int ElemType;
typedef struct node
{
ElemType data;
struct node *next;
}LNode;
void Josephus(int n,int m,int k)
{
LNode *q,*p;
int i;
p=(LNode *)malloc(sizeof(LNode));//申请一个新节点
q=p;
for(i=1;i<n;i++) //for循环吧n-1个人排上号
{
q->data=k; //第一个节点为k,即从k开始
k=k%n+1; //避免k=n的情况
q->next=(LNode *)malloc(sizeof(LNode));
q=q->next; //q一直指向最新的节点
}
q->data=k; //q指向第n个人,k也是第n个数
q->next=p; //尾指针指向头结点,形成循环单链表
printf("依次淘汰的人\n");
while(p->next!=p) //判断是否剩余一个人
{
for(i=1;i<m;i++)
{
q=p; //当从循环出来q在m-1处
p=p->next; //当从循环出来的时候,p节点在m位置处
}
q->next=p->next;//q指向m+1的节点,即淘汰第m个人
printf("%4d",p->data);
free(p);
p=q->next;
}
printf("\n剩的最后一人\n");
printf("%4d",p->data);
}
int main()
{
int n,m,k;
printf("输入人数n,总报数m,开始号k\n");
scanf("%d%d%d",&n,&m,&k);
Josephus(n,m,k);
return 0;
}
运行后结果: