php实现的树形结构数据存取类实例


Posted in PHP onNovember 29, 2014

本文实例讲述了php实现的树形结构数据存取类。分享给大家供大家参考。

具体实现代码如下:

<?php 

/** 

 * Tanphp framework 

 * 

 * 

 * @category   Tanphp 

 * @package    Data_structure 

 * @version    $Id: Tree.php 25024 2012-11-26 22:22:22 tanbo $ 

 */ 

 

/** 

 * 树形结构数据存取类 

 *  

 * 用于对树形结构数据进行快速的存取 

 *  

 * @param array $arr 参数必须为标准的二维数组,包含索引字段(id)与表示树形结构的字段(path),如example中所示 

 *  

 * @example <code> 

 * $arr = array( 

 *  array( 'id' => 1, 'name' => 'php', 'path' => '1' ), 

 *  array( 'id' => 3, 'name' => 'php1', 'path' => '1-3' ), 

 *  array( 'id' => 2, 'name' => 'mysql', 'path' => '2' ), 

 *  array( 'id' => 6, 'name' => 'mysql1', 'path' => '2-6' ), 

 *  array( 'id' => 7, 'name' => 'mysql2', 'path' => '2-7' ), 

 *  array( 'id' => 5, 'name' => 'php11', 'path' => '1-3-5' ), 

 *  array( 'id' => 4, 'name' => 'php2', 'path' => '1-4' ), 

 *   ); 

 *  $cate = new Tree($arr); 

 *   

 *  $data = $cate->getChild(2); 

 *   

 *  print_r($data->toArray()); 

 * </code> 

 *  

 */ 

class Tree 

{ 

    public  $_info;                             //节点信息 

    public  $_child = array();                  //子节点 

    private $_parent;                           //父节点 

    private $_data;                             //当前操作的临时数据 

    private static $_indexs         = array();  //所有节点的索引 

    private static $_index_key      = 'id';     //索引键 

    private static $_tree_key       = 'path';   //树形结构表达键 

    private static $_tree_delimiter = '-';      //属性结构表达分割符 

     

    /** 

     * 构造函数 

     *  

     * @param array $arr 

     * @param boole $force_sort 如果为真,将会强制对$arr 进行排序 

     * @return void 

     */ 

    public function __construct(array $arr = array(),  $force_sort=true) 

    { 

        if ($force_sort === true) { 

            $arr=$this->_array_sort($arr, self::$_tree_key); 

        } 

        if (!emptyempty($arr)) { 

            $this->_init($arr); 

        } 

    } 

     

    /** 

     * 初始存储树形数据 

     *  

     * @param array $arr 

     * @return void 

     */ 

    private function _init(array $arr) 

    { 

        foreach ($arr as $item) { 

            $path        = $item[self::$_tree_key]; 

            $paths       = explode(self::$_tree_delimiter, $path); 

            $count_paths = count($paths); 

            $parent_id   = isset($paths[$count_paths-2]) ? $paths[$count_paths-2] : NULL; 

             

            if (   $count_paths>1                                   //如果有父级 

                && array_key_exists($parent_id, self::$_indexs)      //父级已经被存入索引 

                && self::$_indexs[$parent_id] instanceof Tree    //父级为Tree对象 

            ) { 

                self::$_indexs[$parent_id]->addChild($item); 

            } elseif ($count_paths == 1) { 

                $this->addChild($item); 

            } else { 

                throw new Exception("path数据错误".var_export($item, true)); 

            } 

        } 

         

        //print_r(self::$_indexs); 

    } 

     

    /** 

     * 添加子节点 

     *  

     * @param array $item 

     * @return void 

     */ 

    public function addChild(array $item, $parent = NULL) 

    { 

        $child          = new Tree(); 

        $child->_info   = $item; 

        $child->_parent = $parent == NULL ? $this : $parent; 

        $child->_parent->_child[] =  $child; 

         

        $this->_addIndex($item, $child->_getSelf());  

    } 

     

    /** 

     * 添加节点到索引 

     *  

     * @param array $item 

     * @param mix $value 

     * @return void 

     */ 

    private function _addIndex(array $item, $value) 

    { 

        if (array_key_exists(self::$_index_key, $item) && is_int($item[self::$_index_key])) { 

            self::$_indexs[$item[self::$_index_key]] = $value; 

        } else { 

            throw new Exception("id字段不存在或者不为字符串"); 

        } 

    } 

     

    /** 

     * 获取对自己的引用 

     *  

     * @return Tree object quote 

     */ 

    private function _getSelf() 

    { 

        return $this; 

    } 

     

    /** 

     * 获取指定id的节点的子节点 

     *  

     * @param int $id 

     * @return Tree object 

     */ 

    public function getChild($id) 

    { 

        $data       = self::$_indexs[$id]->_child; 

        $this->_data = $data; 

        return $this; 

    } 

     

    /** 

     * 获取指定id的节点的父节点 

     *  

     * @param int $id 

     * @return Tree object 

     */ 

    public function getParent($id) 

    { 

        $data = self::$_indexs[$id]->_parent; 

        $this->_data = $data; 

        return $this; 

    } 

     

    /** 

     * 获取指定id的节点的同级节点 

     * 

     * @param int $id 

     * @return Tree object 

     */ 

    public function getBrother($id) 

    { 

        $data = self::$_indexs[$id]->_parent->_child; 

        $this->_data = $data; 

        return $this; 

    } 

     

    /** 

     * 将Tree对象转化为数组 

     *  

     * @param  object $object 

     * @return array 

     */ 

     public function toArray($obj = NULL) 

     { 

        $obj  = ($obj === NULL) ? $this->_data : $obj; 

        $arr  = array(); 

        $_arr = is_object($obj) ? $this->_getBaseInfo($obj) : $obj; 

         

        if (is_array($_arr)) { 

            foreach ($_arr as $key => $val){ 

                 

                $val = (is_array($val) || is_object($val)) ? $this->toArray($val) : $val;

                $arr[$key] = $val; 

            } 

        } else { 

            throw new Exception("_arr不是数组"); 

        } 

      

        return $arr; 

    } 

     

    /** 

     * 过滤_parent等字段,以免造成无限循环 

     *  

     * @param object $obj 

     * @return void 

     */ 

    private function _getBaseInfo($obj) 

    { 

        $vars = get_object_vars($obj); 

        $baseInfo['_info']  =  $vars['_info']; 

        $baseInfo['_child'] =  $vars['_child']; 

        return $baseInfo; 

    } 

     

    /** 

     * 二维数组排序 

     * 

     * 根据指定的键名对二维数组进行升序或者降序排列 

     * 

     * @param array  $arr 二维数组 

     * @param string $keys 

     * @param string $type 必须为 asc或desc 

     * @throws 当参数非法时抛出异常 

     * @return 返回排序好的数组 

     */ 

    private function _array_sort(array $arr, $keys, $type = 'asc') { 

        if (!is_string($keys)) { 

            throw new Exception("非法参数keys:参数keys的类型必须为字符串"); 

        } 

     

        $keysvalue = $new_array = array(); 

        foreach ($arr as $k=>$v) { 

            if (!is_array($v) || !isset($v[$keys])) { 

                throw new Exception("参数arr不是二维数组或arr子元素中不存在键'{$keys}'"); 

            } 

            $keysvalue[$k] = $v[$keys]; 

        } 

     

        switch ($type) { 

            case 'asc': 

                asort($keysvalue); 

                break; 

            case 'desc': 

                arsort($keysvalue); 

                break; 

            default: 

                throw new Exception("非法参数type :参数type的值必须为 'asc' 或 'desc'"); 

        } 

     

        reset($keysvalue); 

        foreach ($keysvalue as $k=>$v) { 

            $new_array[$k] = $arr[$k]; 

        } 

        return $new_array; 

    } 

} 

?>

希望本文所述对大家的PHP程序设计有所帮助。

PHP 相关文章推荐
强烈推荐:php.ini中文版(1)
Oct 09 PHP
PHP的开发框架的现状和展望
Mar 16 PHP
php异常处理技术,顶级异常处理器
Jun 13 PHP
ThinkPHP的Widget扩展实例
Jun 19 PHP
分享最受欢迎的5款PHP框架
Nov 27 PHP
非常实用的PHP常用函数汇总
Dec 17 PHP
PHP实现多维数组转字符串和多维数组转一维数组的方法
Aug 08 PHP
CI框架入门之MVC简单示例
Nov 21 PHP
ThinkPHP中类的构造函数_construct()与_initialize()的区别详解
Mar 13 PHP
PHP使用HTML5 FileApi实现Ajax上传文件功能示例
Jul 01 PHP
Laravel框架实现多数据库连接操作详解
Jul 12 PHP
关于PHP5.6+版本“No input file specified”问题的解决
Dec 11 PHP
Codeigniter购物车类不能添加中文的解决方法
Nov 29 #PHP
ThinkPHP模版中导入CSS和JS文件的方法
Nov 29 #PHP
ThinkPHP中Session用法详解
Nov 29 #PHP
thinkphp的静态缓存用法分析
Nov 29 #PHP
thinkphp中memcache的用法实例
Nov 29 #PHP
thinkPHP实现瀑布流的方法
Nov 29 #PHP
php删除左端与右端空格的方法
Nov 29 #PHP
You might like
php 把数字转换成汉字的代码
2015/07/21 PHP
laravel在中间件内生成参数并且传递到控制器中的2种姿势
2019/10/15 PHP
laravel 解决crontab不执行的问题
2019/10/22 PHP
javascript之大字符串的连接的StringBuffer 类
2007/05/08 Javascript
JavaScript实现的日期控件具体代码
2013/11/18 Javascript
判断iframe里的页面是否加载完成
2014/06/06 Javascript
javascript中字符串拼接详解
2014/09/26 Javascript
Javascript实现获取及设置光标位置的方法
2015/07/21 Javascript
js判断手机端(Android手机还是iPhone手机)
2015/07/22 Javascript
jQuery热气球动画半透明背景的后台登录界面代码分享
2015/08/28 Javascript
JavaScript拖拽、碰撞、重力及弹性运动实例分析
2016/01/08 Javascript
JavaScript实现搜索框的自动完成功能(一)
2016/02/25 Javascript
JavaScript事件处理的方式(三种)
2016/04/26 Javascript
AngularJS ng-bind-html 指令详解及实例代码
2016/07/30 Javascript
解决vue 按钮多次点击重复提交数据问题
2018/05/10 Javascript
vue实现微信获取用户信息的方法
2019/03/21 Javascript
JS中箭头函数与this的写法和理解
2021/01/14 Javascript
基于Python实现一个简单的银行转账操作
2016/03/06 Python
Python列表list解析操作示例【整数操作、字符操作、矩阵操作】
2017/07/25 Python
Python cookbook(数据结构与算法)从序列中移除重复项且保持元素间顺序不变的方法
2018/03/13 Python
python实现简易通讯录修改版
2018/03/13 Python
Python实现决策树C4.5算法的示例
2018/05/30 Python
Python3爬虫教程之利用Python实现发送天气预报邮件
2018/12/16 Python
使用APScheduler3.0.1 实现定时任务的方法
2019/07/22 Python
keras实现图像预处理并生成一个generator的案例
2020/06/17 Python
探讨HTML5移动开发的几大特性(必看)
2015/12/30 HTML / CSS
德国奢侈品网上商城:Mytheresa
2016/08/24 全球购物
Club Monaco加拿大官网:设计师男女服装
2019/09/29 全球购物
个人自我评价范文
2014/02/05 职场文书
干部下基层实施方案
2014/03/14 职场文书
外贸会计专业自荐信
2014/06/22 职场文书
毕业论文答辩开场白和答辩技巧
2015/05/27 职场文书
创业计划书之物流运送
2019/09/17 职场文书
python编写函数注意事项总结
2021/03/29 Python
html5表单的required属性使用
2021/07/07 HTML / CSS
全新239军机修复记
2022/04/05 无线电