首页 > 代码库 > 用循环链表解决约瑟夫问题

用循环链表解决约瑟夫问题

约瑟夫问题描述:
从N个人中选出一个领导人,方法如下:所有人排除一个圆圈,按顺序数数,每数到第M的人出局,此时他两边的人
靠拢重新形成圆圈,从已出局人的下一个继续进行。问题是找出哪一个人将会是最后剩下的那个人,甚至我们更希望
知道出局人的顺序。

算法思路:
构造一个循环链表来表示排成圆圈的人。每人的链接指向圆圈内他左边(或者右边)的人。圆圈内人第i个人用整数i
表示。首先为1号构造一个节点的循环链表,然后再把2~N号插入到1号节点之后,得到一个1~N的环,并时x指向节点N
。然后从1号开始,跳过M-1个节点,把第M-1个节点的链接指向M+1号节点,即将第M个出局。继续这个过程,直到剩下
一个节点为止。

实现代码:

 1 #include <stdio.h> 2 #include <stdlib.h> 3  4 typedef struct node* link; 5 struct node {int item; link next;}; 6  7 int main(int argc, char *argv[]) 8 { 9     int i, N=atoi(argv[1]), M=atoi(argv[2]);10     link t = malloc(sizeof *t), x = t;11     t->item = 1;12     t->next = t;13     for(i=2; i<=N; i++)14     {15         x->next = malloc(sizeof *x);16         x = x->next;17         x->item = i;18         x->next = t;19     }20     21     while(x != x->next)22     {23         for(i=1; i<M; i++) x = x->next;24         t = x->next;25         printf("%d\n", t->item);26         x->next = t->next;27         free(t);28     }29     printf("The leader is:%d\n", x->item);30     31     system("pause");32     return 0;33 }

此代码参考了《算法:C语言实现(第1~4部分)》的程序3.9(p52),并做了一些修改。

 

将代码在Dev C++中编译,并将参数设置为9 5(中间用空格隔开),即N为9,M为5,运行结果如下:

5
1
7
4
3
6
9
2
The leader is:8
请按任意键继续. . .

特别的,如果将参数设置为9 1(中间用空格隔开),即N为9,M为1, 结果很容易想到,其如下:

1
2
3
4
5
6
7
8
The leader is:9
请按任意键继续. . .

 

本文参考文献:《算法:C语言实现(第1~4部分)》,机械工业出版社,2011.8

用循环链表解决约瑟夫问题