约瑟夫环
约瑟夫环问题可简化为:
编号为1,2,…,n的n个人按顺时针方向围坐在一张圆桌周围,每人持有一个密码(正整数)。一开始任选一个正整数m作为报数上限值,从第一个人开始按顺时针方向自1开始报数,报到m时停止报数,报m的那个人出列,将他的密码作为新的m值,从他顺时针方向的下一个人开始重新从1报数,数到m的那个人又出列;如此下去,直至圆桌周围的人全部出列为止。要求按出列顺序输出n个人的编号。
由题可知,我们需要先构建一个结构体,其中包括了每个人的编号和密码。1
2
3
4
5
6typedef struct node
{
int id;//**编号**
int pas;//**密码**
struct node *next;
}node,*Lnode;
接下来我的思路是构建一个单向循环链表1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19Lnode create(Lnode L,int n)//用n代表人数
{
L=(Lnode)malloc(sizeof(node));
Lnode p,q;
p=L;
int i=1;
while(n>0)
{
q=(Lnode)malloc(sizeof(node));
p->next=q;
scanf("%d",&q->pas);//输入每个人的密码
q->id=i;
p=q;
n--;
i++;
}
q->next=L->next;
return L;
}
接下来就是实现约瑟夫环,我的思路是若第x个人退出,那么就让指针移动到x-1的位置,然后输出x的编号以后进行删除,令X-1指向X+1。
这个问题还有一些特殊情况需要处理,比如如果刚开始只有一个人,则用if判断以后直接输出编号也就是1就行了,若还剩下两个人,我取巧,直接进行一个奇偶数判定,奇数的话就先输出该节点的编号,偶数就先输出next的编号,然后再输出自身的编号。
代码如下
1 | int ysf(int m,int n) { |
以上便是我对约瑟夫环的理解。