根据二叉搜索树数组建立树结构对象

61 篇文章 0 订阅

前言

二叉树遍历顺序

  • 先序遍历 根->左->右
  • 中序遍历 左->根->右
  • 后良遍历 左->右->根

若将遍历数据当一维数组存储,通常需要中序遍历与 先序或后序两相结合,才能画出一棵完整的二叉树。
但遵行【先上后下,从左右至右】的打描方式,组成的层序单个数组,也可画出一颗树,如下所示(空结点用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;
    }
}

线性思维

  1. 根据数据域创建所有的节点
  2. 遍历所有父节点,根据父子节点索引关系,为其添加左右孩子节点指向
  3. 注意越界情况
// 用面向过程的形式建树
// 先找到所有节点的父节点
# 依据索引值找到父节点: 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)
  1. 根据索引找到父结点
  2. 使用递归与索引相关
  3. 将单一结点创建过程视为一个递归逻辑单元
    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;
    }
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值