约瑟夫问题
问题描述:
约瑟夫(Joseph)问题的一种描述是:编号为1,2,3,…,n的n个人按顺时针方向围坐一圈,每人持有一个密码〈正整数〉,一开始任选一个正整数作为报数上限值m,从第一个人开始按顺时针方向自1开始顺序报数,报到m时停止报数,报m的人出列,将他的密码作为新的m值,从他在顺时针方向上的下一个人开始重新从1报数,如此下去,直至所有人全部出列为止。试设计一个程序求出出列顺序。
基本要求:
利用单向循环链表存储结构模拟此过程,按照出列的顺序打印出各人的编号。
实现提示:
程序运行后首先要求用户指定初始报数上限值,然后读取各人的密码(小于30)。
选作内容:
在顺序存储结构上实现上述问题的操作。
Input
输入包括两行,第一行包括报数上限值m和人数n,第二行为n个人的密码,所有数据之间由空格分隔。
Output
输出一行,共n个整数,表示各编号人的出列顺序。各数之间由空格分隔。
Sample Input
20 7
3 1 7 2 4 8 4
Sample Output
6 1 4 7 2 3 5
#include <stdio.h>
#include <stdlib.h>
typedef struct LNode //结构体定义
{
int id;
int data;
struct LNode *next;
}LNode,*linklist;
linklist CL(linklist L,int n)//创建结构体
{
int i=1;
linklist p,q;
p=(linklist)malloc(sizeof(LNode));
L=p;
q=p;
p->id=i;
while(i<=n)
{
p=(linklist)malloc(sizeof(LNode));
scanf("%d",&(p->data));
p->id=i++;
q->next=p;
q=q->next;
}
p->next=L;
return L;
}
linklist dellist(linklist L,int n,int m)//删除结点
{
linklist p,q;
int i=0,j=0,a;
p=L;
while(p && i<m-1)
{
p=p->next;
i++;/**/
if(p->next==L)
{
i--;
continue;
}
}
q=p->next;
p->next=q->next;
if(p->next==L)
p=p->next;
a=q->data;
printf("%d ",q->id);
free(q);
/**/
while(j<n-1)
{i=0;
while(p && i<a-1)
{
p=p->next;
i++;
if(p->next==L)
{
i--;
continue;
}
}
q=p->next;
p->next=q->next;
if(p->next==L)
p=p->next;
a=q->data;
printf("%d ",q->id);
free(q);
j++;
}
return L;
}
void showlist(linklist L)//输出链表内容,用于调试
{
linklist p;
int n=0;
p=L;
p=p->next;
while(p)
{
printf("|%d ",(p->data));
printf("%d| ",(p->id));
if(p->next==L)
break;
p=p->next;
}
}
int main()
{ linklist L=NULL;
int m,n;
scanf("%d",&m);
scanf("%d",&n);
L=CL(L,n);
//showlist(L);
L=dellist(L,n,m);
//showlist(L);
return 0;
}