php环形链表解决josephu问题

约瑟夫问题:n个小孩围成一圈,从第k个小孩开始数,没数到m的小孩出列。问最后剩下的是谁。

<?php
/**
 * php环形链表解决josephu问题
 */
class child{
	public $no;
	public $next;
	
	public function __construct($no){
		$this->no = $no;
	}
}
$first = null;
$n = 4;//表示有几个小朋友
$m = 3;
$k = 2;
/**
 * addChild函数作用:把$n个小孩构建成一个环形链表,
 * $first变量指向该环形链表的第一个小孩子。
 */
function addChild(&$first,$n){ //为什么加地址符
	//1.头结点不能动
	//内存 ;左堆右栈,中间 全局/静态,文字常量,代码 ;对象实例放在堆内,一般的变量放在栈内;值传递,对象传递,&引用传递。
	$cur = null;
	for($i=0;$i<$n;$i++){
		$child = new child($i+1);  //一个小朋友有也是环形
		if($i==0){ 
			$first = $child;
			$first->next = $first;
			$cur = $first;
		}else{
			$cur->next = $child;
			$child->next = $first;
			$cur = $cur->next;
		}
	}
}

/**
 * 写一个函数显示圈中的小孩子 ,必须把$first给函数
 */
function showChild($first){
	//遍历 $cur变量是帮助我们遍历环形链表,不能动。
	$cur = $first;
	while($cur->next!=$first){
		echo "<br/>小孩的编号是".$cur->no;
		$cur = $cur->next; //没有这句则死循环。
	}
	//当退出while循环时,cur指向了环形链表的最后节点,还要打印最后一个
	echo  "<br/>小孩的编号是".$cur->no;	
}

//开始数数,问题简化,从第一个小孩开始数,数2,看出圈的顺序。
function countChild($first,$m,$k){
	//思考:为了删除小孩,需要一个辅助变量,该变量指向的小孩在first前面;
	$tail = $first;
	while($tail->next!=$first){
		$tail = $tail->next;
	}
	for($i=0;$i<$k-1;$i++){
		$first = $first->next;
		$tail= $tail->next;
	}
	//当退出while时,我们的$tail就指向了最后一个小孩
	//没移动一下,相当于数了一下。移动两次相当于数了3次。
	while($tail!=$first){ //当$tail==$first则说明只有最后一人了。
		for($i=0;$i<$m-1;$i++){
			$tail = $tail->next;
			$first = $first->next;
		}
		$first = $first->next;
		$tail->next = $first;
	}
	echo "<br/>最后留在圈圈中的人的编号是".$first->no;
	
	
}
header("Content-type:text/html; charset=utf-8");
addChild($first,$n);
showChild($first); //有问题吗? 只打印123个小孩
countChild($first,$m,$k);



?>

  

posted @ 2013-07-23 00:35  simpman  阅读(135)  评论(0)    收藏  举报