当前位置 : 主页 > 网络编程 > JavaScript >

用循环单链表演练犹太约瑟夫/猴子选大王问题

来源:互联网 收集:自由互联 发布时间:2021-07-03
原创 用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>

网友评论