前言
二叉树遍历顺序
- 先序遍历 根->左->右
- 中序遍历 左->根->右
- 后良遍历 左->右->根
若将遍历数据当一维数组存储,通常需要中序遍历与 先序或后序两相结合,才能画出一棵完整的二叉树。
但遵行【先上后下,从左右至右】的打描方式,组成的层序单个数组,也可画出一颗树,如下所示(空结点用null表示)
如上所示,实际层的是一棵二叉查找树,它的存储一维数组形态为[10,5,15,3,7,13,18,1,null,6]
。
该数组描述的其实是一个在某序列中寻找6的查找树过程化结果,它并不是被查的数据源,不要尝试用它是重构查找树。换而言之,查找树数据序列,可用从上至下,自左到右的形式画出来。
画二叉查找树
那已知二叉查找树数据[10,5,15,3,7,13,18,1,null,6]
,如何构建树形对象?
class TreeNode
{
public $val = null;
public $left = null;
public $right = null;
public function __construct($value)
{
$this->val = $value;
}
}
线性思维
- 根据数据域创建所有的节点
- 遍历所有父节点,根据父子节点索引关系,为其添加左右孩子节点指向
- 注意越界情况
// 用面向过程的形式建树
// 先找到所有节点的父节点
# 依据索引值找到父节点: lastParent = (index -1 ) / 2
# 依据数组的长度找到最后一个父节点: lastParent = len(li) / 2 - 1
function createTree($list)
{
// 将值列表转为结点列表
$nodeList = array_map(function ($v) {
return new TreeNode($v);
}, $list);
// 计算父结点总数
$parentNum = count($nodeList)/2 -1;
// 由于子节点可根据父节点索引计算出来
// 关键在于 节点关系都是单向,由上向下访问,索引也可据此计算
for ($i=0; $i < $parentNum+1; $i++) {
$leftIndex = 2 * $i + 1;
$rightIndex = 2 * $i + 2;
// 防止越界
$nodeList[$i]->left = $leftIndex < count($nodeList) ? $nodeList[$leftIndex] : null;
// 需考虑越界情况
if ($rightIndex < count($nodeList)) {
$nodeList[$i]->right = $nodeList[$rightIndex];
}else{
break;
}
}
// 返回头结点
return $nodeList[0];
}
// 测试
$root = [10,5,15,3,7,null,18];
$res = createTree($root);
print_r($res);
递归建树
给定【层序数组】即二叉搜索树数据,创建二叉树f (先上层到下层,由左到右,结点不存在为null)
- 根据索引找到父结点
- 使用递归与索引相关
- 将单一结点创建过程视为一个递归逻辑单元
public function buildTree(array $root, int $index=0)
{
// 防止索引越界,无限递归
if ($index >= count($root)) {
return null;
}
// 关注单个结点的创建
// 从根父创建开始,依赖于二叉树父子节点索引这一关键信息
$node = new TreeNode($root[$index]);
// 递归 知道父节点便可顺利创建子节点,而根恰巧也是父节点
// 按层次创建节点,并维护关系【分析当前与下一轮】
$node->left = $this->buildTree($root, $index *2+1);
$node->right = $this->buildTree($root, $index*2+2);
// 返回仍然是根节点引用
return $node;
}
查找树深度
上层下发调用数据 --> 递归调用下层–> 下层返回结果
递归调用点实质是上下交互的边界线,类似前端Vue
中的响应数据,下状态,上事件。
// 求二叉树深度
public function treeDepth(TreeNode $root)
{
if ($root != null) {
$left = $this->treeDepth($root->left);
$right = $this->treeDepth($root->right);
// 递归回调的下半场自动收敛,上半场扩展,同层处于平行空间
// 调用回归时,内层返回值可被外层使用,
return $left > $right ? $left + 1:$right+1;
}
// 最先返回
return 0;
}