中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

利用php怎么實現一個無序樹功能

發布時間:2021-01-25 17:27:10 來源:億速云 閱讀:187 作者:Leah 欄目:開發技術

利用php怎么實現一個無序樹功能?相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。

php代碼如下:

<?php
/* 
用php寫的無序樹
 */
 class unorderedTree{
 // 節點id計數器
 protected $nodeId=0;
 // 樹的深度
 protected $depth=0;
 // 樹的節點數,
 protected $nodesCount=0;
 // 樹的度 @todo: 使其發揮作用
 public $degree=" to be implent";
 // 根節點id
 // 由于樹有多種從根節點開始操作,不想每次遍歷樹到頂找root,用一個變量始終指向根節點
 protected $rootid=null;
 // 子節點集合, k-v 為 nodeid=>(stdclass)node
 // 一些樹的實現常常是采用節點和樹同一class,這里節點是使用 stdclass{ data, parent, id , childrenIds} ,因我認為節點和樹應為兩種對象,且stdclass要輕于樹的class
 // 節點格式說明: $this->nodes[nodeId] = new stdclass{ id ,parentId, childrenIds, data }
 // id: 節點id
 // parentId: 節點父節點id
 // childrenIds: 子節點的id 不想每次遍歷樹確定層次關系 
 // 注意: 節點中, #只保存其自身數據和其子節點id的集合#, 子節點的數據通過從樹 $tree->nodes[ $node->childrenIds[a_child_id] ] 訪問
 // data: 節點中包含的數據,如節點名稱等屬性數據
 protected $nodes=array();
 // 用戶自定義訪問節點
 protected $userVisitFunction=null;
 /* 分組: 類的基本函數 */
 // @todo: 構造樹
 public function __construct(){
 }
 // @todo: 銷毀樹 
 public function __destruct(){
  unset($this->nodes) ;
 }
  //------------ 獲取數據類函數---------------
  // 獲取樹的深度,
  public function getTreeDepth(){
  return $this->depth;
  }
  // 獲取樹的節點數目 
  public function getCount(){
  return $this->NodesCount;
  }
  // 獲取樹的度 
  public function getDegree(){
  // @todo: 獲取樹的度(因為對度暫時沒什么需要就不實現了 )
  return $this->degree;
  }
  //獲取指定節點
  public function getNode($nodeId){
  if(isset($this->Nodes[$nodeId])){
   return $this->Nodes[$nodeId];
  }
  else{
   return false;
  }
  }
  // 獲取最新id
  public function getId(){
  return $this->nodeId;
  }
  //獲取指定節點高度
  public function getNodeHeight($nodeId){
  if( array_key_exists($nodeId, $this->nodes) ){
   // 此節點已在樹里,高度至少為1,每找到一個父節點+1
   $height=1;
   // 記錄此樹中已經訪問過的節點, 用于防止節點構造時互相parent導致此函數死循環且及時結束查找
   $visitedNodesIds=array();
   // 記錄當前操作節點的id
   $cid=$nodeId;
   // 當前節點的父節點必須存在于此樹中
   // 不用遞歸
   while( isset($cid) ) {
    if( !in_array($cid,$visitedNodesIds ) ){
     if( $this->rootid===$cid){ //到頂,返回 
      return $height;
     }
     $visitedNodesIds[]=$cid;
     $cid= $this->nodes[ $cid ]->parentId;
     $height++; 
    }
    else{
     return false;
    }
   }
   return false;
  }
  else{
   return false;
  }
  }
  //獲取根節點
  public function getRoot(){
  return (!is_null($this->rootid) ) && $this->nodes[$this->rootid];
  }
  //獲取指定節點和其所有子節點構成的數組 
  //這是用于獲取子樹的一個關鍵基礎操作
  public function getSubNodes($nodeId){
  if(isset($this->nodes[$nodeId])){
   $result=array();
   $toVisitNodeIds=array();
   $toVisitedNodeIds[]=$nodeId; 
   $result[]=$this->nodes[$nodeId]->id;
   array_shift($toVisitedNodeIds); 
   $toVisitedNodeIds=array_merge( $toVisitedNodeIds, $this->nodes[$nodeId]->childrenIds);
   while(!empty($toVisitedNodeIds)){
    $toVisitNodeId=array_shift($toVisitedNodeIds);
    $result[]=$this->nodes[$toVisitNodeId]->id;
    $toVisitedNodeIds=array_merge( $toVisitedNodeIds, $this->nodes[$toVisitNodeId]->childrenIds);
   }
   return $result ;
  }
  else{
   return false;
  }
  } 
  //@todo: 獲取由指定節點和其所有子節點構建的子樹
  public function getSubTree($nodeid){
  }
  //---------------- 數據更新 -----------------
  public function setId($nodeId){
   $this->nodeId=$nodeId;
   return $this;
  }
  // 創建不重復的(樹中未被使用的) 新id
  public function seekId(){
  $this->nodeId++;
  return $this->nodeId;
  }
 public function setVisitFunction($userFunction){
  $this->userVisitFunction=$userFunction;
  }
  //插入子節點,默認為插在根節點下
  public function insertNode($parent_id=null , $data=null){
  //注意node不是class tree
  $node = new stdclass; 
  $node->data = $data;
  //樹的節點數增加
  $this->nodeCount++;
  // 分配節點id
  $this->seekId();
  $node->id =$this->getId();
  //插入根節點
  if( (is_null($parent_id)) && is_null($this->rootid)){
   $node->parentId = null;
   $node->childrenIds = array();
   $this->depth=1; 
   $this->rootid=$node->id;
   $this->nodes [$node->id]=$node;
   return $this;
  } 
  elseif( isset($this->nodes[$parent_id]) || is_null($parent_id) ){
  // 插在此樹已有節點下
   if(is_null($parent_id)){
    $parent_id=$this->rootid;
   }
   $node->parentId = $parent_id;
   $node->childrenIds = array();
   //更新樹的最大深度
   $depth=$this->getNodeHeight($parent_id);
   $this->depth=max($depth+1, $this->depth);
   $this->nodes[$parent_id]->childrenIds []= $node->id;
   $this->nodes [$node->id]=$node;
   return $this;
  }
  else{
   return $this; 
  }
  } 
  //insert node 的別名
  public function append($parent_id=null , $data=null){
  return $this->insertNode($parent_id,$data);
  }
  // --------------- 數據訪問 -----
  //廣度優先遍歷節點的別名, 全名太長了
  public function b($nodeId=null){
  return $this->breadthTraversal($nodeId);
  }
  // 廣度優先遍歷節點
  public function breadthTraversal($nodeId=null){
  if(is_null($this->rootid)){
   die("此樹為空樹,不可訪問");
  }
  else{
   //全部遍歷
   if(is_null($nodeId) || ( $this->rootid===$nodeId) ){
    $nodeId=$this->rootid;
   }
   $toVisitNodeIds=array();
   $toVisitedNodeIds[]=$nodeId; 
   $this->visit( $this->nodes[$nodeId]);
   array_shift($toVisitedNodeIds); 
   $toVisitedNodeIds=array_merge( $toVisitedNodeIds, $this->nodes[$nodeId]->childrenIds);
   while(!empty($toVisitedNodeIds)){
    $toVisitNodeId=array_shift($toVisitedNodeIds);
    $this->visit( $this->nodes[$toVisitNodeId]);
    $toVisitedNodeIds=array_merge( $toVisitedNodeIds, $this->nodes[$toVisitNodeId]->childrenIds);
   }
  }
  return $this;
  }
  //深度優先的別名
  public function d($nodeId=null){
  return $this->depthTraversall($nodeId);
  }
  // 深度優先遍歷
  // 和廣度優先的不同實現只在于array_merge的順序不同而已 ( php array 忒好用啊忒好用 )
  public function depthTraversall($nodeId=null){
  if(is_null($this->rootid)){
   die("此樹為空樹,不可訪問");
  }
  else{
   //全部遍歷
   if(is_null($nodeId)){
    $nodeId=$this->rootid;
   }
   $toVisitNodeIds=array();
   $toVisitedNodeIds[]=$nodeId; 
   $this->visit( $this->nodes[$nodeId]);
   array_shift($toVisitedNodeIds); 
   $toVisitedNodeIds=array_merge( $this->nodes[$nodeId]->childrenIds, $toVisitedNodeIds );
   while(!empty($toVisitedNodeIds)){
    $toVisitNodeId=array_shift($toVisitedNodeIds);
    $this->visit( $this->nodes[$toVisitNodeId]);
    $toVisitedNodeIds=array_merge( $this->nodes[$toVisitNodeId]->childrenIds, $toVisitedNodeIds );
   }
  }
  return $this;
  }
  //訪問單個節點
  public function visit($node){
  if(is_null($this->userVisitFunction )){
   return $node->id;
  }
  else{
   return call_user_func($this->userVisitFunction,$node,$this);
  }
  }
 }
?>

看完上述內容,你們掌握利用php怎么實現一個無序樹功能的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

php
AI

沿河| 张家川| 咸阳市| 泗洪县| 米林县| 克什克腾旗| 金堂县| 延川县| 公安县| 阜宁县| 山阴县| 昭通市| 崇仁县| 西乌珠穆沁旗| 宁武县| 聊城市| 成安县| 襄城县| 饶阳县| 乾安县| 洪江市| 镇原县| 突泉县| 东辽县| 嵊州市| 岱山县| 苍山县| 沅江市| 随州市| 石首市| 五河县| 休宁县| 崇仁县| 中阳县| 翁牛特旗| 普洱| 盐津县| 华容县| 霞浦县| 互助| 嘉祥县|