【环形链表】丢手帕问题

小朋友丢手帕问题,小朋友的编号(1,2,...,n) ,从k号小朋友开始数,从1开始数到m,当数到m的小朋友出列(1<m<n),问从k号小朋友开始数m,最后剩下几号小朋友?

这里有几点需要注意:

1、链表的头指针不能动,动了就找不着头了$head,一般用一个辅助指针指向头$cur=$head;

2、链表的往后指,在while循环里不要忘了一句话$cur=$cur->next;否则while($cur->next!=null)就死循环了

3、引用传递 在使用addHero时&$first 好好理解引用传递的含义


以下是php的环形链表实现方法

<html>
	<head>
		<meta http-equiv='content-type' content='text/html;charset=gbk'/>
	</head>
	<h1>约瑟夫问题</h1>

	<?php
	
	class Child{
		public $no;
		public $next=null;
		
		public function __construct($no){
			$this->no=$no;			
			}		
		}
		
		
		//定义一个指向第一个小朋友的引用
		$first=null;
		$n=4;//$n表示有几个小朋友
		
		//写一个函数来创建一个四个小朋友的环形链表;
		/**
			addChild函数的作用是:把$n个小孩构成一个环形链表,$first指向第一个孩子
		*/
		//引用传递
		function addChild(&$first,$n){
			//死去活来
			//1.头结点不能动$first不能动
			$cur=null;
				for($i=0;$i<$n;$i++){
					$child=new Child($i+1);		
					
					//怎么构成一个环形链表;
					if($i==0){
						$first=$child;
						$first->next=$child;
						$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循环时,已经到了环形链表的最后,最后还要处理一下最后一个小孩				
			echo '<br/>小孩的编号是'.$cur->no;				 
				
		}
				
		//问题简化,从第一个小孩开始数,数2,看看出圈的顺序
		$m=3;
		$k=2;
				
		function countChild($first,$m,$k){
					
				//思考:因为我们找到一个小孩,就要把他从环形链表中删除
				//为了能够删除某个小孩,我们需要一个辅助变量,该变量指向的小孩在$first前面					
				$tail=$first;
					
				while($tail->next!=$first){						
						$tail=$tail->next;
				}
					
				//考虑一下是从第几个人开始数数
					
				for($i=0;$i<$k-1;$i++){
					$tail=$tail->next;
					$first=$first->next;
						
				}
					
						
				//当退出while时,我们的$tail就指向了最后这个小孩
					
				//让$first和$tail向后移动
				//每移动一次,相当于数了两下;
				//移动2次,相当于数了3下,因为自己数的时候是不需要动的
				//当$tail =$first说明只有一个人了
				while($tail!=$first){
						for($i=0;$i<$m-1;$i++){
							$tail=$tail->next;
							$first=$first->next;
						}
					
				//把first指向的节点小孩删除环形链表					
				echo '<br/> 出圈的编号是'.$first->no;
				$first=$first->next;
				$tail->next=$first;
					
				
				}
				
				echo '<br/> 最后剩下的编号是'.$tail->no;
		}
				
				
				addChild($first,$n);
				showChild($first);				
				countChild($first,$m,$k);
	
	?>
</html>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值