php演算法題(資料結構)
阿新 • • 發佈:2018-10-31
單鏈表的實現
// 單鏈表的操作 public function index() { $list = new \singleLink(); $list->addNode(new \Node(1,'a')); $list->addNode(new \Node(3,'c')); // // 在id=3的前面插入 $list->insert(new \Node(2,'b'),3); // // $list->del(2); // 刪除id=2的節點 // $list->updateToUpper(); // 將所有節點名字的小寫變成大寫 // $list->getNode(); // $list->getNodeLength(); // 單鏈表的逆轉 $list->reverse(); $list->getNode(); } /** * 單向連結串列節點類 */ class Node { public $id; public $name; public $next; public function __construct($id,$name) { $this->id=$id; $this->name=$name; $this->next=null; } } /* ** 單鏈表 */ class singleLink { public $header; function __construct($id=null,$name=null) { $this->header=new Node($id,$name,null); } // 插入一個節點 public function addNode($node) { $current=$this->header; while($current->next!=null){ $current=$current->next; } $node->next=$current->next; $current->next=$node; } // 獲取連結串列 public function getNode() { $current=$this->header; if($current->next==null){ return '連結串列為空'; } while ($current->next!=null) { echo 'id:'.$current->next->id.' '.'name:'.$current->next->name.'<br />'; $current=$current->next; } } // 獲取連結串列長度 public function getNodeLength() { $i=0; $current=$this->header; if($current->next==null){ return '空連結串列'; } while ($current->next!=null) { $i++; $current=$current->next; } echo $i; } // 指定位置插入 public function insert($node,$id) { $current=$this->header; while ($current->next!=null) { if($current->next->id==$id){ $node->next=$current->next; $current->next=$node; return; } $current=$current->next; } return '不存在該節點'; } // 刪除id=$id的節點 public function del($id) { $current=$this->header; while ($current->next!=null) { if($current->next->id==$id){ $current->next=$current->next->next; return; } $current=$current->next; } return '不存在該節點'; } // 將所有的小寫變成大寫 public function updateToUpper() { $current=$this->header; if($current->next==null){ return '空連結串列'; } while($current->next!=null){ $current->next->name=strtoupper($current->next->name); $current=$current->next; } } // 單鏈表的逆轉 public function reverse() { $current=$this->header; $arr=[]; $i=0; while($current->next!=null){ $arr[$i]['id']=$current->next->id; $arr[$i]['name']=$current->next->name; $i++; $current=$current->next; } $this->header->next=null; $arr=array_reverse($arr); foreach ($arr as $index) { $this->addNode(new Node($index['id'],$index['name'])); } } }
雙向連結串列
// 主函式 public function index() { $list=new \doubleLink(); $list->addNode(new \doubleNode(1,'a')); $list->addNode(new \doubleNode(3,'c')); $list->insert(new \doubleNode(2,'b'),3); // 在id=3的前面插入 $list->del(2); //刪除id=2的節點 dump($list); $list->getNodeLength(); } // 雙向連結串列節點類 class doubleNode { public $id; public $name; public $prev; public $next; public function __construct($id,$name) { $this->id=$id; $this->name=$name; $this->prev=null; $this->next=null; } } /** * 雙向連結串列類 */ class doubleLink { public $header; function __construct($id=null,$name=null) { $this->header=new doubleNode($id,$name,null,null); } // 加入一個節點 public function addNode($node) { $current=$this->header; while ($current->next!=null) { $current=$current->next; } $node->next=$current->next; $current->next=$node; $node->prev=$current; } // 獲取連結串列長度 public function getNodeLength() { $current=$this->header; $i=0; while ($current->next!=null) { $i++; $current=$current->next; } echo $i; } public function insert($node,$index) { $current=$this->header; while ($current->next!=null) { if($current->next->id==$index){ $node->next=$current->next; $current->next=$node; $current->prev=$current; break; } $current=$current->next; } } // 刪除一個節點 public function del($index) { $current=$this->header; while ($current->next!=null) { if($current->next->id==$index){ $current->next->next->prev=$current; $current->next=$current->next->next; } $current=$current->next; } } }
實現氣泡排序:每一次迴圈都將最大的數放到最後,時間複雜的 n^2 該方法最優的時間複雜度是 n
public function index() { $arr=[10,11,11,12,13,14,15,16]; shuffle($arr); $tmp=''; for($i=0;$i<count($arr);$i++) { $flag=1; for($j=0;$j<count($arr)-$i-1;$j++) { if($arr[$j]>$arr[$j+1]){ $tmp=$arr[$j]; $arr[$j]=$arr[$j+1]; $arr[$j+1]=$tmp; $flag=0; } } if($flag==1) break; } dump($arr); }
快速排序:選擇一個基點,大於該值的放在右邊,小於的放在左邊,遞迴實現,平均使勁按複雜度是:nlog2n
public function index()
{
$arr=[10,11,11,12,13,14,15,16];
shuffle($arr);
$arr=self::qsort($arr);
dump($arr);
}
public function qsort($arr)
{
if(count($arr)<=1){
return $arr;
}
$left=$right=[];
$length=count($arr);
for($i=1;$i<$length;$i++)
{
if($arr[$i]>$arr[0]){
$right[]=$arr[$i];
}else{
$left[]=$arr[$i];
}
}
$left=self::qsort($left);
$right=self::qsort($right);
return array_merge($left,array($arr[0]),$right);
}
簡單選擇排序 每一次找出一個最小的值放在最前面時間複雜度 n^2
public function index()
{
$arr=[10,11,11,12,13,14,15,16];
shuffle($arr);
$length=count($arr);
for($i=0;$i<$length;$i++)
{
for($j=$i+1;$j<$length;$j++)
{
if($arr[$j]<$arr[$i]){
$min=$arr[$j];
$arr[$j]=$arr[$i];
$arr[$i]=$min;
}
}
}
dump($arr);
}
堆排序,使用資料結構二叉樹的原理,時間複雜度:nlog2n
public function index()
{
$arr=[10,11,11,12,13,14,15,16];
shuffle($arr);
$length=count($arr);
self::dsort($arr,$length);
for($i=$length-1;$i>0;$i--)
{
self::swap($arr,$i,0);
$length--;
self::dsort($arr,$length);
}
dump($arr);
}
// 找出最小的那一個節點,並把它放在第一的位置
public function dsort(&$arr,$length)
{
$index=intval($length/2)-1;
for($index;$index>=0;$index--)
{
if(($index*2+1)<$length){
$min=$index*2+1;
if($index*2+2<$length&&$arr[$index*2+2]<$arr[$min]){
$min=$index*2+2;
}
if($arr[$index]>$arr[$min]){
self::swap($arr,$index,$min);
}
}
}
}
// 交換陣列中兩個元素的位置
public function swap(&$arr,$one,$two)
{
$tmp=$arr[$one];
$arr[$one]=$arr[$two];
$arr[$two]=$tmp;
}
二叉樹的廣度優先和深度優先演算法實現
public function index()
{
$root=new \doubleNode('1','a');
$node2=new \doubleNode('2','b');
$node3=new \doubleNode('3','c');
$node4=new \doubleNode('4','d');
$node5=new \doubleNode('5','e');
$node6=new \doubleNode('6','f');
$node7=new \doubleNode('7','g');
$node8=new \doubleNode('8','h');
$root->prev=$node2;
$root->next=$node3;
$node2->prev=$node4;
$node2->next=$node5;
$node3->prev=$node6;
$node3->next=$node7;
$node4->prev=$node8;
// $depth=[];
// self::depth($root,$depth);
// dump($depth);
// dump(self::depth($root));
// 廣度遍歷遞迴用法
dump(self::breadth($root));
}
// 深度優先,使用遞迴
public function depth($btree,&$arr)
{
array_push($arr, $btree->id);
if($btree->prev!=null){
self::depth($btree->prev,$arr);
}
if($btree->next!=null){
self::depth($btree->next,$arr);
}
return;
}
// 深度遍歷,棧實現
public function depth($btree) {
$return_msg = array();
$stack = array();
array_push($stack, $btree);
while (!empty($stack)) {
$node=array_pop($stack);
$return_msg[] = $node->id;
if ($node->next!=null)
array_push($stack, $node->next);
if ($node->prev!=null)
array_push($stack, $node->prev);
}
return $return_msg;
}
// 廣度優先 ,佇列實現
function breadth($btree) {
$return_msg = array();
$queue = array();
array_push($queue, $btree);
while (!empty($queue)) {
$node=array_pop($queue);
$return_msg[] = $node->id;
if ($node->prev!=null) array_unshift($queue, $node->prev);
if ($node->next!=null) array_unshift($queue, $node->next);
}
return $return_msg;
}
有一個a,他有2個子目錄b,c和一個檔案d,b有兩個檔案e,f,c有一個目錄g,g有一個檔案h,找出所有的檔案和目錄
public function index($path='D:\a'){
$dh = opendir($path);
while($d = readdir($dh)){
if($d=='.' || $d == '..'){
continue;
}
echo $d.'<br />';
if(is_dir($path.'/'.$d)){
self::index($path.'/'.$d);
}
}
return ;
}