古代某法官要判决n个犯人死刑,他有一条荒唐的逻辑,将犯人首尾相接排成圆圈,然后从第s个人开始数起,每数到第m个犯人,就拉出来处决;然后又数m个,数到的犯人又拉出来处决,以此类推。剩下的最后一人可以赦免。
编写程序,给出处决顺序,并给出哪一个人可以活下来。
注:大体的思路以及需要注意的点都在注释中了,直接上代码了。
//定义结点
typedef struct _josephus
{
int num;
struct _josephus *next;
}josephus;
int n; //全局变量,记录共有几名犯人(结点)
//犯人数目(创建结点)
josephus *Creat(josephus *pHead)
{
josephus *pEnd,*pNew;
int i;
printf("犯人数:");
scanf("%d",&n);
for(i = 1; i <= n; i++)
{
pNew = (josephus *)malloc(sizeof(josephus));
pNew->num = i;
pNew->next = NULL;
if(pHead == NULL)
pHead = pNew;
else
pEnd->next = pNew;
pEnd = pNew;
}
pEnd->next = pHead; //令尾指针指向头结点
return pHead;
}
//处决函数
josephus *fun(josephus *pHead, int s, int m)
{
josephus *temp = pHead;
josephus *p = NULL; //指向要处决的犯人(结点)
int i;
//遍历寻找到起始位置
for(i = 1; i < s; i++)
temp = temp->next;
printf("kill: ");
//循环判断处决犯人(删除结点)
while(n > 1)
{
p = temp;
for(i = 1; i < m; i++)
{
temp = p;
p = p->next;
}
printf("%d ",p->num);
temp->next = p->next; //将要处决的犯人(结点)前后连接起来
free(p);
temp = temp->next; //处决完一次后,还要继续处决到只剩一个犯人,因此temp指向被删除结点的下一个结点
n--;
}
printf("\n");
return temp;
}
int main()
{
int s,m;
josephus *pHead = NULL;
pHead = Creat(pHead);
printf("s,m: ");
scanf("%d %d",&s,&m);
pHead = fun(pHead,s,m);
printf("存活: %d\n",pHead->num);
free(pHead);
pHead = NULL; //防止产生野指针
return 0;
}
!@#$%^&*~