- 用单循环链表解决
约瑟夫问题用单链表解决时注意3中特殊情况:
(1)【count==m/count!=m时】p指针恰好指向L头结点时
(2)当pre指针恰好指向L头结点时
(3)当删除了报m的元素后,pre->next为头指针
本质问题:应保证pre,p指针指向的结点应有具体数值不是头结点
#include<stdio.h>
#include<stdlib.h>
typedef struct Lnode
{
int data;
Lnode *next;
} Lnode,*Linknode;
void init(Linknode &L)
{
L=(Linknode)malloc(sizeof(Linknode));
L->next=L;
}
void enter(Linknode &L,int e)
{
Linknode s=(Linknode)malloc(sizeof(Lnode));
s->data=e;
Linknode p=L;
while(p->next!=L)
{
p=p->next;
}
s->next=p->next;
p->next=s;
}
bool delet(Linknode &L,Linknode p,Linknode pre)//删除链表中的第n个元素
{
pre->next=p->next;
printf("%d ",p->data);
free(p);
return true;
}
int print(Linknode L)
{
Linknode p=L->next;
int i=0;
while(p!=L)
{
// printf("%d ",p->data);
i++;
p=p->next;
}
return i;
}
void cir(Linknode &L,int n,int m) //约瑟夫环
{
int j=1; //j:用于判断报的数
for(int i=0;i<n;i++)
{
enter(L,i+1);
}
Linknode p=L->next,p1,pre=L;
while(1)
{
if (print(L)==1) //只剩下最后一个人
{
printf("%d ",L->next->data);
break;
}
if(j==m)
{
if(p==L) //当j==m且指针指向头结点时
{
p=L->next;
pre=L;
}
delet(L,p,pre);
if(pre->next==L)
{
p=L->next;
}
else
{
p=pre->next;
}
j=1;
}
else
{
if(p==L)
{
p=L->next;
pre=L;
j++;
}
else
{
p=p->next;
j++;
pre=pre->next;
}
}
}
}
void destory(Linknode &L)
{
Linknode p=L->next,p1;
while(p->next!=L)
{
p1=p->next;
free(p);
p=p1;
}
free(p);
free(L);
}
int main()
{
Linknode L;
init(L);
cir(L,5,3);
destory(L);
return 0;
}