(三十二)完全二叉树节点的个数

本文探讨了如何有效地计算普通二叉树和完全二叉树的节点数量。对于普通二叉树,提供了一个递归法,时间复杂度为O(N)。而对于完全二叉树,提出了两种解法,一种利用树的高度,时间复杂度为O(h^2),另一种根据左右子树的满二叉树特性,时间复杂度更低。这些方法有助于在处理大规模二叉树结构时提高效率。
摘要由CSDN通过智能技术生成

       求一个节点个数为N的普通二叉树的节点的个数,可以直接遍历二叉树,求出节点个数。时间复杂度为O(N),可用递归法,层序遍历等方法,以下是递归法的代码:

【C++】

int getNodeNum(TreeNode* node){
	if(node == NULL)
		return 0;
	int leftNum = getNodeNum(node->left);
	int rightNum = getNodeNum(node->right);
	return leftNum + rightNum + 1;
}

       因为完全二叉树比较特殊,故可以利用完全二叉树的性质来求节点个数,可使得时间复杂度小于O(N)。

【解法一】若二叉树层数为h,则时间复杂度为O(h2)

  • 如果head == NULL,说明是空树,直接返回0;
  • 如果不是空树,就求树的高度。求法是看树的最左节点能到哪一层,层数记为h;(普通二叉树此方法不通)
  • 递归过程,记为bs(node,l,h);node表示当前节点,l表示node所在的层数,h表示整棵树的层数是始终不变的。bs(node,l,h)返回的是以node为头节点的完全二叉树的节点数是多少。此过程分为两种情况
    • (1)左子树为满二叉树。通过node右子树的最左节点来判断。如果能到达最后一层,说明node的整颗左子树都为满二叉树,层数为h-1层,则左子树节点个数为(2h-1 -1)个,加上本身节点,则为(2h-1 )个。然后再计算出右子树的节点数:bs(node->right,l+1,h)。结果为2^h-1^ + bs(node->right,l+1,h)
    • (2)右子树为满二叉树。通过node右子树的最左节点来判断。如果不能到达最后一层,说明node的整颗右子树都为满二叉树,层数为h-l-1层,则左子树节点个数为(2h-l-1 -1)个,加上本身节点,则为(2h-l-1 )个。然后再计算出右子树的节点数:bs(node->left,l+1,h)。结果为2^h-l-1^ + bs(node->right,l+1,h)
      在这里插入图片描述

【C++】

/*函数声明*/
int getCBTNodeNum(TreeNode* head);/*求完全二叉树节点个数*/
int bs(TreeNode* node,int l,int h);/*求以node为节点的完全二叉树的节点个数*/
int mostLeftLevel(TreeNode* node,int level);/*求以node节点为头节点的层数*/

int getCBTNodeNum(TreeNode* head){
	if(head == NULL)
		return 0;
	return bs(head,1,mostLeftLevel(head,1));
}

int bs(TreeNode* node,int l,int h){
	if(l == h)
		return 1;
	if(mostLeftLevel(node->right,l+1) == h){
		return (1 << (h-l)) + bs(node->right,l+1,h);
	}else{
		return (1 << (h-l-1)) + bs(node->left,l+1,h);
	}
}

int mostLeftLevel(TreeNode* node,int level){
	TreeNode* cur = node;
    while(cur != NULL){
		level++;
		cur = cur->left;
	}
	return level - 1;
}

【解法二】

把二叉树分为两种情况

  • 满二叉树:可以直接用 2h - 1 来计算,h为根节点深度。

  • 非满二叉树:最后一层叶子节点没有满。分别递归左孩子,和右孩子,递归到某一深度一定会有左孩子或者右孩子为满二叉树,然后依然可以按照情况1来计算

在这里插入图片描述

【C++】

int getCBTNodeNum2(TreeNode* head){
    if(head == NULL)
        return 0;
    TreeNode* left = head->left;
    TreeNode* right = head->right;
    int leftHeigh = 0,rightHeight = 0;
    while(left){//左子树深度
        left = left->left;
        leftHeigh++;
    }
    while(right){
        right = right->right;
        rightHeight++;
    }

    if(leftHeigh == rightHeight){
        return (2 << leftHeigh) - 1;//满二叉树
    }
    return getCBTNodeNum2(head->left) + getCBTNodeNum(head->right);
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值