1. 程式人生 > >php演算法題(資料結構)

php演算法題(資料結構)

單鏈表的實現

// 單鏈表的操作
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 ;
}