算法题:约瑟夫环问题
原题:
N个人围成一圈顺序编号,从1号开始按1、2、3…顺序报数,报p者退出圈外,其余的人再从1、2、3开始报数,报p的人再退出圈外,以此类推。 请按退出顺序输出每个退出人的原序号。
输入格式:
输入只有一行,包括一个整数N(1<=N<=3000)及一个整数p(1<=p<=5000)。
输出格式:
按退出顺序输出每个退出人的原序号,数据间以一个空格分隔,但行尾无空格。
输入样例:
7 3
输出样例:
3 6 2 7 5 1 4
实现
使用单向循环链表解决这个问题。
#include <stdio.h>
#include <stdlib.h>
typedef struct node{
int date;
struct node *next;
}node,*cmd; //创建链表
cmd create(); //创建函数
void print(cmd L); //输出函数
int a,b; //一共a个数,报b则出链
int main()
{
cmd L;
scanf("%d %d",&a,&b);
L=create();
print(L);
return 0;
}
cmd create() // 创建含有 1 2 3....a个数的链表
{
int i;
cmd L,p,s;
L=(cmd)malloc(sizeof(node));
p=L;
p->date=1;
for(i=2;i<=a;i++){
s=(cmd)malloc(sizeof(node));
s->date=i;
p->next=s;
p=s;
}
p->next=L; //循环链表
return L;
}
void print(cmd L)
{
int i=0,j,r[1000]; //数组存放出列数字
cmd q,p; //删除链结点所需
p=L;
while(i<a){
for(j=1;j<(b-1);j++){ //将目标停在要报b
p=p->next;} 的前一个结点
q=p->next; //做删除结点
r[i]=q->date; //出链的结点date保存到
p->next=q->next; 数组里
free(q);
p=p->next;
i++;
}
for(j=0;j<=a-1;j++)
printf("%d ",r[j]);
}