约瑟夫问题:
据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从,Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。
这样一个问题通常都被作为计算机专业开始学习编程语言的一个小课题。这里就写一下自己的做法了。代码使用C写的。功能也算比较完善的吧。
首先,这个问题有很多种解决方法。本文的这种方法算是比较容易理解的。并且实现了多种功能
算法实现:
使用双向环形链表,假设有5个数字,从1号数字开始数,3个数字循环一趟:
首先有几个问题需要解决:
1、 建立链表
这个环节中比较麻烦的就是最后一个元素的建立。最后一个元素的next指针要指向第一个元素。第一个元素的prev指针要指向最后一个元素。如图
2、 如何删除一个元素
其实删除一个元素只要把前一个元素的指针指向删除元素的后一个元素即可。假如要删除3号,只要如图即可:
这样就把3号排除在了链表之外。
3、 如何判读结束条件。这个简单,环形链表长度为1即可了。
首先定义一个节点结构体:
接着时间对一个节点的初始化工作:
第一个temp节点表示要初始化的节点。ne==next,p==prev;
接下来就是建立一个环形链表的工作了。
参数n表示链表的长度;用temp节点当作游标节点。
下面这几个函数是建立游戏参数的函数:
下面是游戏进行过程函数:
最后有一个额外的函数用来打印环形链表,用来进行调试或者查看每一步进行后的结果。
这样约瑟夫问题得以解决。