约瑟夫环问题
有n个人按1、2、3、┈、n的顺序顺时针围成一圈,每人持有一个密码(正整数)。开始时任选一个整数作为报数上线值m,从第1个人开始顺时针自1开始顺序报数,报道m时停止报数。报m的人出圈,将他的密码作为新的m值,接着从出圈的下一个人开始重复此过程,直到所有人出圈为止。要求设计一个程序,利用单循环链表模拟此过程,按照出圈顺序输出各人的编号。
例如,m的初值为20,n值为7,7个人的密码依次为3,1,7,2,4,8,4,则各人的出圈顺序为6,1,4,7,2,3,5。
//约瑟夫环
#include<stdio.h>
#include<stdlib.h>
typedef struct node
{
int data_1;//序号
int data_2;//密码
struct node *next;
}Node;
struct node *p,*pt,*head;
int main()
{
int n, a, i, m, j;
printf("请输入总人数:n= ");
scanf("%d",&n);
head=(struct node *)malloc(sizeof(Node));//创建一个带头结点的链表
p=head;
for(i=1;i<n;i++)//创建循环链表
{
pt=(struct node *)malloc(sizeof(Node));
p->next=pt;
p=p->next;//p=pt;
}//p为最后一个结点
p->next=head;
printf("\n密码依次为:passwords= ");
pt=head;
for(i=1;i<=n;i++)
{
scanf("%d",&a);
pt->data_1=i;//序号
pt->data_2=a;//密码
pt=pt->next;//pt后移
}
pt=p;
//pt->next=head;
printf("\n报数上限值(m>0):m= ");
scanf("%d",&m);
printf("\n出圈顺序为:");
for(i=1;i<=n;i++)//删除n个结点,循环n次
{
for(j=1;j<m;j++) //pt=1,j=2; pt=m-1,j=m
{
pt=pt->next;
}//pt为第m-1个结点
p=pt->next;//p的值可变
printf("%d ",p->data_1);//出圈结点的序号
m=p->data_2;
pt->next=p->next;//第m个结点和第m+1个结点
free(p);//释放第m个结点
}
system("pause");
}
请输入总人数:n= 7
密码依次为:passwords= 3 1 7 2 4 8 4
报数上限值(m>0):m= 20
出圈顺序为:6 1 4 7 2 3 5 Press any key to continue . . .