改自韩顺平老师的算法公开课。
1、单链表。
使用单链表解决水浒英雄排行问题。
<!doctype html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>链表</title> </head> <body> <h1>水浒英雄排行榜</h1> <hr style="width:300px;margin:0;"/> <?php class Hero{ public $no; //名次 public $name; //名字 public $nickname; //外号 public $next=null; //链表 public function __construct($no='',$name='',$nickname=''){ $this->no=$no; $this->name=$name; $this->nickname=$nickname; } } //遍历链表 function showHero($head){ $cur=$head; while($cur->next!=null){ echo '英雄排名:'.$cur->next->no.'|'.$cur->next->name.'|'.$cur->next->nickname.'<br/>'; $cur=$cur->next; } } //添加英雄(有顺序) function addHero($head,$hero){ $cur=$head; $flag=false; //表示没有重复编号 while($cur->next!=null){ if($cur->next->no>$hero->no){ break; }elseif($cur->next->no==$hero->no){ echo $hero->no.'号位置已经被占领!<br/>'; $flag=true; } $cur=$cur->next; } if(!$flag){ $hero->next=$cur->next; $cur->next=$hero; } } //删除英雄 function delHero($head,$no){ $cur=$head; $flag=false; //假设没有找到 while($cur->next!=null){ if($cur->next->no==$no){ $flag=true; break; //找到 } $cur=$cur->next; } if($flag){ $cur->next=$cur->next->next; }else{ echo '没有找到要删除的英雄<br/>'; } } //修改英雄 function updateHero($head,$hreo){ $cur=$head; while($cur->next!=null){ if($cur->next->no==$hreo->no) break; $cur=$cur->next; } if($cur->next==null){ //说明没找到要修改的英雄 echo '您要修改的英雄不存在<br/>'; }else{ $cur->next->name=$hreo->name; $cur->next->nickname=$hreo->nickname; } } $head=new Hero(); $hero=new Hero(1,'宋江','及时雨'); addHero($head,$hero); $hero=new Hero(2,'卢俊义','玉麒麟'); addHero($head,$hero); $hero=new Hero(4,'吴用','智多星'); addHero($head,$hero); $hero=new Hero(6,'林冲','豹子头'); addHero($head,$hero); $hero=new Hero(1,'joe','牛人'); updateHero($head,$hero); delHero($head,9); showHero($head); ?> </body> </html>
2、循环链表。
使用循环链表解决约瑟夫问题(丢手帕问题)
<?php //小孩类 class Child{ public $no; public $next=null; public function __construct($no){ $this->no=$no; } } //添加n个小朋友 function addChild(&$first,$n){ $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; } } } //遍历所有小孩 function showChild($first){ $cur=$first; while($cur->next!=$first){ //显示 echo '<br/>小孩的编号:'.$cur->no; $cur=$cur->next; } //while循环最后一个节点没有打印出来 echo '<br/>小孩的编号:'.$cur->no; } //解决josephu function josephu($first,$m,$k){ $tail=$first; $count=0; //计数器 while($tail->next!=$first){ //使$tail指向最后一个小孩 $tail=$tail->next; } //把first定位的第k个小孩,从第k个小孩数起 for($i=0;$i<$k-1;$i++){ $first=$first->next; $tail=$tail->next; } while($tail!=$first){ $count++; //数到$m for($i=0;$i<$m-1;$i++){ $first=$first->next; $tail=$tail->next; } echo '<br/>第'.$count.'个出列的小孩是:'.$first->no; $first=$first->next; $tail->next=$first; } echo '<br/>最后留在圈子里的人是:'.$tail->no; } $first=null; //第一个小朋友 $n=4; //表示有n个小朋友 $m=2; //表示数到m的人出列 $k=3; //表示从第k个人开始数 addChild($first,$n); showChild($first); josephu($first,$m,$k); ?>
3、堆栈
使用PHP对数组模拟出栈、入栈
<html> <head> <meta http-equiv='content-type' content='text/html;charset=utf-8'/> </head> <h1>使用数组来模拟栈的各种操作</h1> <?php class MyStack{ private $top=-1;//默认是-1,表示该栈是空的 private $maxSize=5;//$maxSize表示栈最大容量 private $stack=array();// //入栈的操作 public function push($val){ //先判断栈是否已经满了 if($this->top==$this->maxSize-1){ echo '<br/>栈满,不能添加'; return; } $this->top++; $this->stack[$this->top]=$val; } //出栈的操作,就是把栈顶的值取出 public function pop(){ //判断是否栈空 if($this->top==-1){ echo '<br/>栈空'; return; } //把栈顶的值,取出 $topVal=$this->stack[$this->top]; $this->top--; return $topVal; } //显示栈的所有数据的方法. public function showStack(){ if($this->top==-1){ echo '<br/>栈空'; return; } echo '<br/>当前栈的情况是....'; for($i=$this->top;$i>-1;$i--){ echo '<br/> stack['.$i.']='.$this->stack[$i]; } print_r($this->stack); } } $mystack=new MyStack; $mystack->push('西瓜'); $mystack->push('香蕉'); $mystack->push('橘子'); $mystack->push('柚子'); $mystack->push('柚子x'); $mystack->showStack(); $val=$mystack->pop(); echo '<br/>pop出栈了一个数据'.$val; $mystack->showStack(); $val=$mystack->pop(); echo '<br/>pop出栈了一个数据'.$val; $mystack->showStack(); $val=$mystack->pop(); echo '<br/>pop出栈了一个数据'.$val; $mystack->showStack(); $val=$mystack->pop(); echo '<br/>pop出栈了一个数据'.$val; $mystack->showStack(); ?> </html>
注意$this->stack使用pop出栈后,$this->stack本身并没有改变
4、选择排序算法
<?php //选择排序 function selectSort($arr){ for($i=0;$i<count($arr)-1;$i++){ $minValue=$arr[$i]; //假设$arr[$i]为最小值 $minIndex=$i; //假设最小值的索引 for($j=$i+1;$j<count($arr);$j++){ if($minValue>$arr[$j]){ $minValue=$arr[$j]; $minIndex=$j; } } //交换 $temp=$arr[$i]; $arr[$i]=$arr[$minIndex]; $arr[$minIndex]=$temp; } return $arr; } //测试 $arr=array(8,-1,6,10); $arr=selectSort($arr); print_r($arr); ?>
5、冒泡排序算法
<?php //冒泡排序算法 function bubbleSort($arr){ $count=count($arr); if($count<=1) return $arr; for($i=0;$i<$count-1;$i++){ for($j=$count-1;$j>$i;$j--){ if($arr[$j]<$arr[$j-1]){ $temp=$arr[$j]; $arr[$j]=$arr[$j-1]; $arr[$j-1]=$temp; } } } return $arr; } //测试 $arr=array(8,-1,6,10); $arr=selectSort($arr); print_r($arr); ?>
6、插入排序算法
<?php //插入排序算法 function insertSort($arr){ for($i=1;$i<count($arr);$i++){ $insertValue=$arr[$i]; //待插入的值 $insertIndex=$i-1; //下一步与插入值比较的值的索引 while($insertIndex>=0&&$insertValue<$arr[$insertIndex]){ $arr[$insertIndex+1]=$arr[$insertIndex]; $insertIndex--; } $arr[$insertIndex+1]=$insertValue; } return $arr; } //插入排序法假设数组中只有一个元素,并且是有序的 //测试 $arr=array(0,5,-1); $arr=insertSort($arr); print_r($arr); ?>
执行效率:插入算法>选择算法>冒泡算法