题目
给出一个完全二叉树,求出该树的节点个数
分析
求出当前节点的左边界的深度。若当前节点的右节点的左边界高度等于h,那么左子树就是满二叉树,使用公式求出节点数,递归求出右子树的节点个数。
若当前节点的右节点的左边界高度不等于h,那么右子树就是满二叉树。使用公式求出节点数,递归求出左子树的节点个数。
代码
public static class Node {
public int value;
public Node left;
public Node right;
public Node(int data) {
this.value = data;
}
}
//主函数 得到h
public static int nodeNum(Node head) {
if (head == null) {
return 0;
}
return bs(head, 1, mostLeftLevel(head, 1));
}
//变量:当前节点;当前层;整棵树的深度
public static int bs(Node node, int l, int h) {
if (l == h) {
return 1;
}
//返回值是以当前节点为头的整棵树的节点个数
//右子树最左的深度是否达到左边界的深度
//主函数传进来的l是node的层数,当求子节点的递归时,l要加1
if (mostLeftLevel(node.right,l+1) == h) {
//达到深度,1 << (h - l)=2^(1 << (h - l))
// 也就是左树节点个数加当前节点个数。左为满二叉树。递归求右子树。
return (1 << (h - l)) + bs(node.right, l + 1, h);
} else {
//未达到深度。右子树是满二叉树。递归求左子树。
return (1 << (h - l - 1)) + bs(node.left, l + 1, h);
}
}
//求当前节点最左边界到达哪一层
public static int mostLeftLevel(Node node, int level) {
while (node != null) {
level++;
node = node.left;
}
return level - 1;
}
public static void main(String[] args) {
Node head = new Node(1);
head.left = new Node(2);
head.right = new Node(3);
head.left.left = new Node(4);
head.left.right = new Node(5);
head.right.left = new Node(6);
System.out.println(nodeNum(head));
}