约瑟夫问题:标号从1到n的n个人围成一个圈,从1开始计数到m的人退出圈子,然后从退出的下一个人开始接着从1计数,数到m的人后继续退出,最后只剩下一个人,求剩下人的编号。这便是约瑟夫问题的模型。
约瑟夫问题分析:
约瑟夫问题是一道典型的模拟问题。如果采用一般的方法模拟难度较大,代码也较长。
采用链表的方法可以使问题更加容易解决。链表是一种基于指针运用的数据结构。对于初学者或者指针运用不熟练的来说实现链表模拟比较困难。
本人green hand,参考Robert Sedgewick大牛的代码作此篇文章,以实现链表解决约瑟夫问题,同时对链表做一些介绍。
code:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef struct node *link;//用指针表示指向下一节点的链接
struct node{int item;link next;};// 链表的建立 item表示节点
int main()
{
while(1)
{
int n,m,i;
scanf("%d%d",&n,&m);//读入n个人,数到m的人退出
//为1号创建一个节点t 并构造该节点的循环链表
link t=(link)malloc(sizeof *t),x=t;
t->item=1;t->next=t;
//把2-N号插入到1号节点之后 链表插入过程
for(i=2;i<=n;i++)
{
x=(x->next=(link)malloc(sizeof *x));
x->item=i;
x->next=t;
}
//由此得到了一个循环链表 即一个1-n的环
//模拟约瑟夫踢出人的过程
while(x!=x->next)//循环结束条件 是否剩下最后一个人
{
for(i=1;i<m;i++)//从1开始跳过m-1个节点
x=x->next;
x->next=x->next->next;//把第m-1个节点的链接指向m+1号节点
n--;//除去计数为m的人
}
printf("%d\n",x->item);
}
return 0;
}
全部代码:
1 #include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 typedef struct node *link; 5 struct node{int item;link next;}; 6 int main() 7 { 8 9 while(1) 10 { 11 int n,m,i; 12 scanf("%d%d",&n,&m); 13 link t=(link)malloc(sizeof *t),x=t; 14 t->item=1;t->next=t; 15 for(i=2;i<=n;i++) 16 { 17 x=(x->next=(link)malloc(sizeof *x)); 18 x->item=i; 19 x->next=t; 20 } 21 while(x!=x->next) 22 { 23 for(i=1;i<m;i++) 24 x=x->next; 25 x->next=x->next->next; 26 n--; 27 } 28 29 printf("%d\n",x->item); 30 } 31 return 0; 32 }
关于链表:
链表是一组数据项的集合,其中每个数据项都是一个节点的一部分,每个节点都包含指向下一个节点的链接。
链表的构建:
1 typedef struct node *link; 2 struct node {Item item;link next;};
创建一个节点的结构体实例:
1 link x=(link)malloc(sizeof *x);
删除节点x:
1 t=x->next;x->next=t->next; 2 更简单的语句: 3 x->next=x->next->next;
把节点t插入节点x后的下一个位置:
1 t->next=x->next; 2 x->next=t; 3 删除不再使用的节点: 4 t=x->next; 5 x->next=t->next; 6 free(t);