在以前,遇到无限极分类返回一个节点的所有子孙节点时,我都是用递归计算的,后来发现时间复杂度和空间复杂度都太高了,后来自己研究了一下改进了算法.
节点数据如下:键值对分别是自己对应父亲节点
<?php $tree=array( 1=>0, 2=>1, 3=>2, 4=>3, 5=>4, 6=>5, 7=>6, 8=>7, 9=>8, 10=>9, 11=>10, 12=>11, 13=>12, 14=>13, 15=>14, 16=>15, 17=>16, 18=>17, 19=>18, 20=>19, 21=>20, 22=>21, 23=>22, 24=>23, 25=>24, 26=>25, 27=>26, 28=>27, 29=>28, 30=>29, 31=>30, 32=>31, 33=>32, 34=>33, 35=>34, 36=>35, 37=>36, 38=>37, 39=>38, 40=>39, 41=>40, 42=>41, 43=>42, 44=>43, 45=>44, 46=>45, 47=>46, 48=>47, 49=>48, 50=>49, 51=>50, 52=>51, 53=>52, 54=>53, 55=>54, 56=>55, 57=>56, 58=>57, 59=>58, 60=>59, 61=>60, 62=>61, 63=>62, 64=>63, 65=>64, 66=>65, 67=>66, 68=>67, 69=>68, 70=>69, 71=>70, 72=>71, 73=>72, 74=>73, 75=>74, 76=>75, 77=>76, 78=>77, 79=>78, 80=>79, 81=>80, 82=>81, 83=>82, 84=>83, 85=>84, 86=>85, 87=>86, 88=>87, 89=>88, 90=>89, 91=>90, 92=>91, 93=>92, 94=>93, 95=>94, 96=>95, 97=>96, 98=>97, 99=>98, 100=>99,//如果是递归的方法 到这一层的时候 就报错了 可以注释该层 ); ?>
以往算法如下:
<?php function get_list($tree,$id=0) { static $list=array();//定义静态数组存放子孙 foreach ($tree as $key => $v) { if($v==$id) { $list[]=$key;//把子孙放入数组中 unset($tree[$key]);//去掉这个数组的键 避免无效循环 get_list($tree,$key);//再次调用自身,把子节点变成父节点去寻找子孙 } } return $list;//返回数组 } ?>
结果如图
去掉最后一层的那个元素 就可以获取了。
这说明这样的算法在遇到节点层级非常深的时候会崩溃,例如超过100层,php会报错误的。后来改进了一种算法如下:
<?php $id=2; $new_array=array();//存放子孙的数组 $id_list[]=$id;//存放父亲的数组 //遍历所有子孙数据 每次去取已经有的数据的子孙 并把它加入父亲数组 for ($i=1; $i <= count($tree); $i++) { foreach ($tree as $key => $v) { if( in_array($v,$id_list) ) { $new_array[$key]=$v;//把我放进子孙数组 $id_list[$key]=$key;//把子孙也放入父亲数组 unset($tree[$key]);//这个已经用过了可以回收了避免无效循环 } } } $son_list=array_keys($new_array);//拿到存放子孙的数组 取键即可 print_r($son_list); exit(); ?>