侯体宗的博客
  • 首页
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

php无序树实现方法

php  /  管理员 发布于 7年前   174

本文实例讲述了php无序树实现方法。分享给大家供大家参考。具体如下:

运行效果如下图所示:

php代码如下:

(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程序设计有所帮助。

您可能感兴趣的文章:

  • PHP超牛逼无限极分类生成树方法
  • php从数据库查询结果生成树形列表的方法
  • php通过前序遍历树实现无需递归的无限极分类
  • php遍历树的常用方法汇总
  • PHP使用递归生成文章树
  • php简单实现无限分类树形列表的方法
  • PHP生成树的方法


  • 上一条:
    PHP实现的json类实例
    下一条:
    分享PHP函数实现数字与文字分页代码
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • PHP 8.4 Alpha 1现已发布!(0个评论)
    • 用Time Warden监控PHP中的代码处理时间(0个评论)
    • 在PHP中使用array_pop + yield实现读取超大型目录功能示例(0个评论)
    • Property Hooks RFC在PHP 8.4中越来越接近现实(0个评论)
    • 近期文章
    • 在windows10中升级go版本至1.24后LiteIDE的Ctrl+左击无法跳转问题解决方案(0个评论)
    • 智能合约Solidity学习CryptoZombie第四课:僵尸作战系统(0个评论)
    • 智能合约Solidity学习CryptoZombie第三课:组建僵尸军队(高级Solidity理论)(0个评论)
    • 智能合约Solidity学习CryptoZombie第二课:让你的僵尸猎食(0个评论)
    • 智能合约Solidity学习CryptoZombie第一课:生成一只你的僵尸(0个评论)
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(95个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2017-06
    • 2017-07
    • 2017-08
    • 2017-09
    • 2017-11
    • 2017-12
    • 2018-01
    • 2018-02
    • 2018-03
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2020-07
    • 2020-09
    • 2021-02
    • 2021-03
    • 2021-04
    • 2021-05
    • 2021-06
    • 2021-07
    • 2021-08
    • 2021-09
    • 2021-10
    • 2021-11
    • 2021-12
    • 2022-01
    • 2022-02
    • 2022-05
    • 2022-06
    • 2022-07
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-02
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-06
    • 2023-07
    • 2023-08
    • 2023-09
    • 2023-10
    • 2023-11
    • 2023-12
    • 2024-01
    • 2024-02
    • 2024-03
    • 2024-04
    • 2024-05
    • 2024-06
    • 2024-07
    • 2024-09
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客