改自韓順平老師的算法公開課。
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); ?>
執行效率:插入算法>選擇算法>冒泡算法