问题描述:
这里删除操作频繁,我们用单循环链表解决这个问题比较方便,注意当只有一个结点时的处理问题。
下面的代码是自行输入数据(不一定是自然数每次递增1的数列),每一个数据代表一个人,输出出圈的序列。
#include
#include
#define maxsize 100
typedef struct list
{
int data;
struct list*next;
} Lnode,*Linklist;
Linklist creat(int *arr,int len)//创建单循环链表
{
int i;
Linklist head,tail,ptr;
head=(Linklist)malloc(sizeof(Lnode));
if(!head)
{
printf("内存分配失败!");
return NULL;
}
head->data=arr[0];
head->next=NULL;
tail=head;
for(i=1; idata=arr[i];
ptr->next=NULL;
tail->next=ptr;
tail=tail->next;
}
ptr->next=head;//使最后结点的后继指向头结点,形成循环链表
return head;
}
void rotation(Linklist s,int m,int i)//循环圈函数,实现目标数出圈函数
{
Lnode *p,*q;int cout=0,delete=0;
p=s;
q=p;//q为待删结点的前驱,p为待删结点
while(delete%d",p->data);
q->next=p->next;
free(p);
delete++;//记录已删除数据的个数,防止只有一个结点时进入死循环
p=q;
cout=0;
}
q=p;
p=p->next;
}
}
int main()
{
Linklist s;
int arr[maxsize];
int i=0,j=0,flag=1,x,m;
printf("please input the nums(-1 is stand for stopping):\n");
while(flag)//将数据存储到arr数组中
{
scanf("%d",&x);
if(x==-1)
flag=0;
else
{
arr[i]=x;
i++;
}
}
s=creat(arr,i);
while(jdata);
s=s->next;
j++;
}
printf("\nplease input the nums you want to go out:\n");
scanf("%d",&m);
rotation(s,m,i);
return 0;
}
下面是从1开始报数,初始的m值由用户给定
#include
#include
#define maxsize 100
typedef struct
{
int num;
int data;
} nums;
typedef struct
{
nums stu[maxsize];
int last;
} seqlist;
seqlist* init(int arrsize)
{
seqlist* L;
L=(seqlist*)malloc(sizeof(seqlist));
L->last=arrsize-1;
return L;
}
seqlist* creat(int n)
{
seqlist* s;
int x,i;
s=init(n);
printf("please input the secret nums of everyone:\n");
for(i=0; istu[i].data=x;
}
for(i=0; istu[i].num=i+1;
}
return s;
}
void result(seqlist* s,int n,int m)
{
int i=0,j,count=0;
int k=0,flag=0;
while(countlast)
{
while(s->stu[i].num!=m)//若num不是m则继续报数
{
if(i>s->last)
i=0;
else
{
s->stu[i].num=++k;
i++;
}
}
m=s->stu[i].data;
printf("->%d",s->stu[i].data);
for(j=i+1; j<=s->last; j++)
{
s->stu[j-1].num=s->stu[j].num;
s->stu[j-1].data=s->stu[j].data;
// flag=1;//记录有数据出队
}
// i--;
s->last--;
//数据出队后重置序号
k=0;
for(j=i; j<=s->last; j++)//for(j=i+1; j<=s->last; j++)
{
s->stu[j].num=++k;
}
for(j=0; jstu[j].num=++k;
}
count++;//记录删除的数据个数
// i++;
}
}
int main()
{
seqlist* s;
int n,m;
printf("please input the nums of the people:\n");
scanf("%d",&n);
printf("please input a num you want to go out at first:\n");
scanf("%d",&m);
s=creat(n);
result(s,n,m);
return 0;
}
约瑟夫环的输出序列
输入如下:
5//代表指定的人数n
3//第一个开始报数的人的编号k(1<=k<=5)
4//报数上限值m
输出如下:
1 5 2 4 3 //输出序列
输入输出样例:1组
#1
5
3
4
1 5 2 4 3
#include
#include
#define maxsize 100
typedef struct list
{
int data;
struct list *next;
} Lnode,*Linklist;
Linklist creat(int *arr,int len)//创建单循环链表
{
int i;
Linklist head,tail,ptr;//
head=(Linklist)malloc(sizeof(Lnode));
if(len>1)//若不止一个数,进行链表插入处理
{
if(!head)
{
printf("内存分配失败!");
return NULL;
}
head->data=arr[0];
head->next=NULL;
tail=head;//首尾相连
for(i=1; idata=arr[i];
ptr->next=NULL;
tail->next=ptr;
tail=tail->next;
}
ptr->next=head;//使最后结点的后继指向头结点,形成循环链表
return head;
}
else//只有一个数,进行首尾相连操作
{
if(!head)
{
printf("内存分配失败!");
return NULL;
}
head->data=arr[0];
head->next=NULL;
tail=head;
tail->next=head;//首尾相连
return head;
}
}
void rotation(Linklist s,int m,int n,int num)//循环圈函数,实现目标数出圈函数
{
Lnode *p,*q;
int cout=0,delete=0;
p=s;
q=p;//q为待删结点的前驱,p为待删结点
while(p->data!=num)//先找到编号为num的数字
{
q=p;
p=p->next;
}
while(deletedata);
q->next=p->next;
free(p);
delete++;//记录已删除数据的个数,防止只有一个结点时进入死循环
p=q;
cout=0;
}
q=p;
p=p->next;
}
}
int main()
{
Linklist s;
int arr[maxsize];
int i=0,j=0,m,n,num;
//printf("please input the nums(-1 is stand for stopping):\n");
scanf("%d",&n);//输入个数
for(i=1; i<=n; i++) //赋值
{
arr[i-1]=i;
}
s=creat(arr,n);
scanf("%d",&num);//开始报数的编号
scanf("%d",&m);//报数的上限,即报到那个数就出圈
// printf("\nplease input the nums you want to go out:\n");
rotation(s,m,n,num);
return 0;
}