原创 用javascript循环单链表演练犹太约瑟夫/猴子选大王问题 WalkthroughforJewishJosephus/MonkeysProblem viaCircularSingleLinkedList 一群孩儿的游戏 一群孩儿共M个人,每人都有编号,编号是1,2,3...
用 javascript 循环单链表演练犹太约瑟夫/猴子选大王问题
Walkthrough for Jewish Josephus/Monkeys Problem
via Circular Single Linked List
一群孩儿的游戏
一群孩儿共M个人,每人都有编号,编号是1,2,3 ...M。按照1--M
的顺序依次围坐一圈。从1号开始数,数到第N个,这个孩子就要离开此圈。然后,从下一个孩子开始,再数到第N个,这个孩子就要离开此圈。
这样依次下来,
1. 直到圈中只剩下最后两个人,这两个人的编号是多少?(犹太约瑟夫问题Jewish Josephus Problem )
2. 直到圈中只剩下最后一个人,这一个人的编号是多少?(猴子选大王问题 The monkeys elect their king)
其实,为选择规则所输入的数字,为最后留下的成员个数.
演示见:
http://runjs.cn/detail/mevhmdap
http://sandbox.runjs.cn/show/mevhmdap
参考:
http://www.pudn.com/downloads409/sourcecode/book/detail1743390.html
http://blog.sina.com.cn/s/blog_7027c3cf0100w9nn.html
1. [图片] Monkey_Josephus_1.png
2. [图片] monkey_josephus_2.png
3. [文件] Josephus_Monkey.html ~ 7KB 下载(2)
<!protrammer: Xu Tongchun, June 30, 2016
猴子选大王
任务:一堆猴子都有编号,编号是1,2,3 ...m ,这群猴子(M个)按照1--M
的顺序围坐一圈,从第1开始数,每数到第N个,该猴子就要离开此圈,
这样依次下来,直到圈中只剩下最后一只猴子,则该猴子为大王。
Jewish Josephus Problem
传说在公元1世纪的犹太战争中,犹太约瑟夫是公元一世纪著名的历史学家。在罗马人占领乔塔帕特后,39 个犹太人与约瑟夫及他的朋友躲到一个洞中,
39个犹太人决定宁愿死也不要被敌人俘虏,于是决定了一个流传千古的自杀方式,
41 (M)个人排成一个圆圈,由第1个人开始报数,每报 到第3(N)人该人就必须自杀,
然后再由下一个人重新报数,直到所有人都自杀身亡为止。
然而约瑟夫和他的朋友并不想遵从这个约定,约瑟夫要他的朋友先假装遵从,
他将朋友与自己安排在第_个和第_个位置,于是逃过了这场死亡游戏,
你知道安排在了第几个嘛?
>
<html>
<head>
<title>Cercular Linked List</title>
<meta charset="utf-8">
<script type="text/javascript">
function Node(data){ // 创建一个结点的构造方法
this.data = data;
this.next = null;
}
function CList(data) { //循环链表的构造方法
this.head = new Node(data); //数据成员
this.head.next = this.head; //数据成员
this.count=1; //数据成员
this.find = find; //成员方法
this.stepForward = stepForward; //成员方法
this.insertLast = insertLast;//成员方法
this.traversal = traversal; //成员方法
this.findPrevious = findPrevious; //成员方法
this.remove = remove; //成员方法
}
/*循环链表 Clist 的成员方法 find(data)的定义.
* 查询数据为 data 的结点。
* 若找到,返回该结点的引用。 若没有找到, 返回 空
*/
function find(data) {
var p = this.head;
while(p.data!=data && p.next != this.head)
p=p.next;
if (p.data==data)
return p;
else
return null;
}
/*循环链表 Clist 的成员方法 stepForward(p,n) 的定义.
* 从 p 结点开始报数,报到第 n 个结点,返回第 n 个结点
*/
function stepForward(p,n) {
var q = p;
for (var i=1; i<n; i++)
q = q.next;
return q;
}
/*循环链表 Clist 的成员方法 insertLast(data) 的定义.
* 将 数据项为 data 的结点,插入循环链表的尾部。
*/
function insertLast(data) {
var newNode = new Node(data);
var p = this.head;
while(p.next!=this.head)
p=p.next;
newNode.next=this.head;
p.next=newNode;
this.count++;
}
/*循环链表 Clist 的成员方法 : 遍历 traversal() 的定义.
*/
function traversal() {
var p = this.head;
var s = "Total Number: " + this.count + "<br>";
do{
s += p.data + " ";
p=p.next;
} while (p != this.head);
return s;
}
/*循环链表 Clist 的成员方法 findPrevious(p) 的定义.
* 返回 p 结点的 前继(前一个)结点。
*/
function findPrevious(p) {
var q = this.head;
while (q.next != p && q.next != this.head)
q=q.next;
return q;
}
/*循环链表 Clist 的成员方法 remove(data) 的定义.
* 删除 数据项为 data 的结点、 返回被删除的结点。
* 若结点不存在,则返回 空。
*/
function remove(data) {
var p = this.find(data);
if (p) {
var q= this.findPrevious(p);
if ( p == this.head)
this.head=p.next;
q.next=q.next.next;
this.count--;
return p;
} else
return null;
}
function solution(){ // 用按钮触发的方法
/* 起始有 M 个人. 由第 1 个人开始报数,每报到第 N 个人,
* 该人就从循环链表被清除
* 若是“猴子选大王”问题,g 取 1.
* 若是"犹太约瑟夫"问题,g 取 2.
*/
var M= document.forms[0].elements[0].value;
var N= document.forms[0].elements[1].value;
var g= document.forms[0].elements[2].value;
/* 用户输入的数据 M 和 N 数必须是一个大于 1 的整数
* 检查 M 和 N 的 合法性 guard for validity
*/
if( isNaN(M) || M%1 != 0 || M <= 1) {
alert("初始总数必须是一个大于 1 的整数");
return ;
}
if( isNaN(N) || N%1!=0 || N <= 1) {
alert("数到数 N 必须是一个大于 1 的整数");
return ;
}
var s = ""; // 记录演练过程的字符串
if (g==1)
s+="演练规则:猴子选大王 The rule adopted for \"Monkeys elect their king\".";
else
s+="演练规则:犹太约瑟夫 The rule adopted for \"Jewish Josephus Problem \".";
s+="<br>演练过程如下(结果见最后一行) Thewalkthrough is reported as follows. The final result is seen at the last line:<br>";
var list = new CList(1);
for (var i = 2; i <= M; i++)
list.insertLast(i);
s+=list.traversal() + "<br>";
var cur=list.head;
/* 若是“猴子选大王”问题,g 取 1.
* 若是"犹太约瑟夫"问题,g 取 2.
*/
while(list.count>g ){
var p_deleted = list.remove((list.stepForward(cur,N)).data);
cur=p_deleted.next;
s+=p_deleted.data + " is deleted. ";
s+=list.traversal() + "<br>";
// 将 s 显示于容器 <div id="display"></div> 之中
document.getElementById("display").innerHTML=s;
}
}
</script>
<style>
.inner{
width:500px;
}
.out{
width:100%;
border:solid #0F0;
margin-bottom:5px;
}
td{
height:40px;
width=250px;
border:solid #FF0;
}
</style>
</head>
<body>
<table class="out" width=100%><tr><td>
<form onSubmit="solution();return false" name='example'>
<table class="inner"><caption>用循环单链表演练犹太约瑟夫/猴子选大王问题<br>Walkthrough for Jewish Josephus/Monkeys Problem <br>via Circular Single Linked List</caption>
<tr><td>
初始总数 M<br>initial numbber M :</td><td> <input type="text" name="initial_number" >
</td></tr><tr><td>
数到第 N 个<br>counting to N each time:</td><td><input type="text" name="step_width" ></td>
</tr><tr><td>选择规则 The rule adopted for</td><td>
<input name="text" type="text" /></td></tr>
<tr><td><input type="Submit" value="演练 Walkthroug"></td></tr>
</table>
</form>
</td><td>
<div>选择规则说明:<br>
输入的数字,为最后留下的成员个数.<br>
输入 1 为选择 "猴子选大王 Monkeys elect their king"<br>
输入 2 为选择 "犹太约索夫 Jewish Josephus" </div>
</td></tr></table>
<div id="display"></div>
</body>
</html>
