在以前,遇到无限极分类返回一个节点的所有子孙节点时,我都是用递归计算的,后来发现时间复杂度和空间复杂度都太高了,后来自己研究了一下改进了算法.
节点数据如下:键值对分别是自己对应父亲节点
<?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();
?>