二叉树基础2:计算二叉树的节点个数(根据二叉树类型)

根据二叉树类型 计算二叉树的节点个数

普通二叉树

如果是一颗普通的二叉树,应该怎么计算节点的个数呢?

我们可以递归每一个节点的左节点和右节点,最后加上自己,就是所有的节点个数

java代码:

    //todo 计算树的节点个数(遍历)
    public int getTreeNodeCount(TreeNode root){
        //递归当前节点的left和right
        if(root==null)return 0;
        int leftCount = getTreeNodeCount(root.left);
        int rightCount = getTreeNodeCount(root.right);
        return leftCount+rightCount+1;
    }

这种方式递归深度为logn,空间O(logn),时间为O(n)

满二叉树:

如果是一颗满二叉树呢?是否有更简单的方法呢

首先看看满二叉树的特点:

比如节点个数=2^树的深度-1

那么

我们对于满二叉树来说只需计算它的深度即可

但是我们对于一颗二叉树来说 并不知道它是满二叉树,还是普通二叉树

所以

我们需要先判断二叉树的类型 再选择对应的简便算法 去得到这个节点的个数

java代码:

//todo 是否是完美二叉树(满二叉树)
public boolean isPerfectBinaryTree(TreeNode root){
    //满二叉树的定义即 节点个数=2^高度-1。
    //也就是说每一个被遍历的节点要么有俩个子节点,要么没有子节点
    //所以可以 遍历每一个节点,如果该节点满足上述其中一个就递归的检查它的left和right
    if(root==null)return true;//空树 -> 也是满二叉树
    if((root.left==null&&root.right==null)||(root.left!=null&&root.right!=null)){
        //递归left和right
        boolean leftIsPerfectBinaryTree = isPerfectBinaryTree(root.left);
        boolean rightIsPerfectBinaryTree = isPerfectBinaryTree(root.right);
        return leftIsPerfectBinaryTree&&rightIsPerfectBinaryTree;
    }else {
        return false;
    }
}    
//todo 根据判断是否为满二叉树 来计算节点个数
public int getTreeNodeCountByPerfectTree(TreeNode root){
    boolean perfectBinaryTree = isPerfectBinaryTree(root);
    if(perfectBinaryTree){
        //求深度,然后2^高度-1
        int height=0;
        while (root!=null){
            root=root.left;
            height++;
        }
        return (int) (Math.pow(2,height)-1);
    }else {
        return getTreeNodeCount(root);
    }
}

但是这样的思路貌似比之前普通遍历要复杂一点且时间空间都没有提升。

但一般题目为给出树为满二叉树的先决条件,我们只需求一下深度再求2^深度-1即可

我这里的代码是作为学习所用

完全二叉树

那么对于完全二叉树呢?

我们再来看看完全二叉树的构造,

在这里插入图片描述

你会发现

只要是完全二叉树,root一定有一个子树为满二叉树。

这就给了我们一个思路

只要判断出:root的左子树是满二叉树,还是右子树是满二叉树,
如果左子树是慢二叉树,那么左子树按照满二叉树的算法去求左子树的节点个数,而右子树就按普通求法即可
如果右子树是满二叉树,则同理

那么怎么判断左右子树 谁是那颗满二叉树呢?

用俩个探头指针,一个向左下,一个右下,分别直到叶子节点,计算二者的深度

一致,说明该节点 就是 满二叉树的root,直接通过求幂得出该root下的节点个数

不一致,说明它不是满二叉树的root,则直接递归left和right+1。

java代码:

//todo 完全二叉树 计算节点个数
    public int getTreeNodeByCompleteTree(TreeNode root){
        //完全二叉树 介于 普通二叉树-满二叉树
        //而完全二叉树的子树中 必定有一颗 满二叉树
        //所以我们可以 让满二叉树按照满二叉树计算方式算,普通按照普通二叉树算
        //具体:遍历每一个节点,计算在当前节点对左右子树的深度,
        //      若相等,说明该节点是满二叉的节点,直接返回2^深度-1
        //      否则,说明该节点是普通二叉树的节点,就按普通的方式计算
        TreeNode left=root,right=root;
        int leftHeight=0,rightHeight=0;
        while (left!=null){
            left=left.left;
            leftHeight++;
        }
        while (right!=null){
            right=right.right;
            rightHeight++;
        }
        if(leftHeight==rightHeight){
            return (int) (Math.pow(2,leftHeight)-1);
        }
        else {
            int leftCount = getTreeNodeCount(root.left);
            int rightCount = getTreeNodeCount(root.right);
            return leftCount+rightCount+1;
        }
    }
### 计算二叉树中指定节点的层数 对于二叉树而言,可以通过递归方法来计算特定节点所在的层数。假设根节点位于第0层,在遍历过程中每向下深入一层,则当前层次加一。 #### 方法描述: 为了找到目标节点并返回其所在层数,可以从根节点开始进行深度优先搜索(DFS),当遇到匹配的目标值时记录下此时所处的高度作为最终的结果。如果到达叶子节点仍未发现目标,则回溯至上一级继续探索其他路径直到成功定位为止。 以下是Python代码实现这一逻辑的方式: ```python class TreeNode: def __init__(self, val=0, left=None, right=None): self.val = val self.left = left self.right = right def find_depth(root: TreeNode, target_val, current_level=0) -> int: # 如果当前节点为空说明已经到底部但仍没找到目标节点 if not root: return -1 # 当前节点就是要找的那个节点 if root.val == target_val: return current_level # 向左子树寻找 left_result = find_depth(root.left, target_val, current_level + 1) # 左边找到了就不用再去右边找了 if left_result != -1: return left_result # 继续向右子树寻找 return find_depth(root.right, target_val, current_level + 1) # 构建测试用例中的二叉树结构 root = TreeNode('A') root.left = TreeNode('B') root.right = TreeNode('C') root.left.left = TreeNode('D') root.left.right = TreeNode('E') root.right.right = TreeNode('F') root.left.left.left = TreeNode('G') root.left.left.right = TreeNode('H') root.left.right.right = TreeNode('I') print(f"The depth of node 'G' is {find_depth(root, 'G')}") # 输出应为2 ``` 此函数`find_depth()`接受三个参数:要查询的二叉树节点、待查找的目标节点值以及可选的初始层级编号,默认设为零表示从根节点出发[^4]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

编程就是n踢r

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值