你的老师留这个作业了吗?
1.题目
编程题:Jesephus问题(猴子选大王)
有n个人围一圈,从第s人开始数数,s为1,依次数到m,m出局,至最后一人为主。
要求:
用c语言编写一程序,读入n,s,m,建立一个循环链表,每个节点依次装入自然数1,2,……,n,
实现上述操作,且每一个出圈者加入同一链栈中,最后输出大王序号,及依出局次序号。``
2.题目分析
很明确的告知了是Jesephus问题,从选人的过程来说,我们选用循环链表来操作,为什么是链表而不是数组?
1.链表可以很好的把n个人连成一个圈
2.对选出的序号,链表也更易实现删除操作
3.题目要求建立循环链表
很明确选人过程用链表即可实现,那么为什么要用链栈?
1.可以用栈来存放选出来的序号
2.出栈的“先进后出”可以实现一个逆序的功能
3.题目要求
总的来说,这是考察Jesephus算法及链表链栈的题目。
3.解题思路分析
1.创建结点,用来表示不同的人,每个结点里面的data类型为int型,目的是存放n个从1开始自然数来表示结点序号。
2.读入n之后,利用循环创建长度为n的循环链表,并为每个结点存入对应的序号。
3.找到选人开始的初始位置,问题指定为s=1。
4.选人过程利用双循环。外循环控制选人次数,当有n个人,那么选出n-1或n个人即可。内循环进行具体选人,利用读入的m对循环进行控制,每当选出一人,就要对该结点进行删除。也可再利用(p->data==(p->next)->data)这样一个条件来判断选人是否结束。
5.利用链栈存储序号。可以先写好入栈函数,把入栈函数放在上面的4中的循环里面,这样就直接把选出来的序号存储到链栈。
6.显示排名。编写出栈函数即可
4.代码及截图检验
#include<stdio.h>
#include<stdlib.h>
/*jesephus问题*/
typedef int datatype;
typedef struct node/*创建结点*/
{
datatype data;
struct node *next;
}node;
node *head;
node *top;
void Push(int x)/*入栈函数*/
{ node *p;
p=(node *)malloc(sizeof(node));
p->data=x;
p->next=top;
top=p;
}
void ShowStack()/*显示栈中所有的元素*/
{ node *p;int x=1;
p=top;
if(p->data==0)printf("\t\t\t 栈中无元素!\n");
else
{
while(p->data!=0)
{
printf("名次 %03d 序号 %2d\n",x,p->data);
p=p->next;
x++;
}
}
}
int main()
{
int n,m,s,i,j;
printf("请依次输入总人数n,自然数m。(用空格隔开)\n");
scanf("%d%d",&n,&m);
s=1;
printf("\n本题已经指定开始位置为 s=1\n");
node *p,*q;
head=(node *)malloc(sizeof(node));
head->next=NULL;
top=(node *)malloc(sizeof(node));
top->next=NULL;
top->data=0;
p=head;/*指针p指向头结点*/
i=n;j=1;
while(i)
{
q=(node *)malloc(sizeof(node)); /*为新结点q申请分配内存*/
q->data=j++;/*读入数据*/
q->next=p->next;/*q结点指针域指向p结点指针域*/
p->next=q;/*指向新的结点*/
p=q;
i--;
}
printf("\n");
p->next=head->next;/*循环链表,最后一个结点指向第一个结点*/
p=head;/*指针p指向头结点*/
i=s-1;
while(i)/*找到指定位置s=1*/
{
p=p->next;
i--;
}
j=1;int x=1;
while(j)/*选人*/
{
i=m-1;
while(i)
{
p=p->next;
i--;
}
q=p->next;
printf("第%2d个入栈为 序号%d\n",x,q->data);
Push(q->data);
x++;
p->next=q->next;
free(q);
if(p->data==(p->next)->data)j=0;
}
Push(p->data);
printf("第%2d个入栈为 序号%d\n\n",x,p->data);
ShowStack();
return 0;
}
欢迎指点交流!
写稿不易,感谢支持!