求一个节点个数为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)
。
- (1)左子树为满二叉树。通过node右子树的最左节点来判断。如果能到达最后一层,说明node的整颗左子树都为满二叉树,层数为h-1层,则左子树节点个数为(2h-1 -1)个,加上本身节点,则为(2h-1 )个。然后再计算出右子树的节点数:
【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);
}