Find the largest Complete Subtree in a given Binary Tree in C++


Concept

With respect of a given Binary Tree, the task is to determine the size of maximum complete sub-tree in the given Binary Tree.

Complete Binary Tree – A Binary tree is treated as Complete Binary Tree if all levels are completely filled without possibly the last level and the last level has all keys as left as possible.It has been noted that all Perfect Binary Trees are Complete Binary tree but reverse in NOT true. It has been seen that if a tree is not complete then it is also not Perfect Binary Tree.

Input 

      2
     / \
    3   4
   / \  / \
  5   6 7  8
 / \ /
9 10 11

Output 

Size : 10
Inorder Traversal : 9 5 10 3 11 6 2 7 4 8
The above given tree is a complete binary tree.

Input 

      51
     / \
   31    61
   / \   / \
  6 21 46   71
 /
11

Output 

Size : 4(With respect of right subtree)
Inorder Traversal : 11 46 61 71
The above given tree is not a complete binary tree.

Method

Simply visit the tree in bottom up manner. Next with respect of on coming up in recursion from child to parent, we can transfer information about sub-trees to the parent. The transferred information can be applied by the parent to perform Complete Tree test (for parent node) only in constant time. In this case,both left and right sub-trees require totell the parent information whether they are perfect or not and complete or not and they also need to return the maximum size of complete binary tree found till now.

We should note that the sub-trees need to transfer the following information up the tree for determining the largest complete sub-tree so that we can compare the maximum size with the parent’s data to verify the Complete Binary Tree property.

  • A bool variable should be exist to verify whether the left child or the right child sub-tree is Perfect and Complete or not.

  • Again we have to verify that from left and right child calls in recursion we find out if parent sub-tree is Complete or not by following 3 cases −

    • It has been seen that if left subtree is perfect and right is complete and there height is also same then sub-tree root is also treated as complete binary subtree with size equal to sum of left and right subtrees plus one (for current root).

    • It has been seen that if left subtree is complete and right is perfect and the height of left is larger than right by one then sub-tree root is complete binary subtree with sizeequal to sum of left and right subtrees plus one (for current root). But root subtree cannot be declared as perfect binary subtree because in this case its left child is not perfect.

    • Else this sub-tree cannot be treated as a complete binary tree and simply return the largest sized complete sub-tree found till now in the left or right sub-trees.So it can be concluded that if tree is not complete then it is not perfect also.

Example

 Live Demo

//This is a C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
// Node structure of the tree
struct node1 {
   int data;
   struct node1* left;
   struct node1* right;
};
// For creating a new node
struct node1* newNode(int data){
   struct node1* node1 = (struct node1*)malloc(sizeof(struct node1));
   node1->data = data;
   node1->left = NULL;
   node1->right = NULL;
   return node1;
};
// Shows structure for return type of
// function findPerfectBinaryTree
struct returnType {
   // For storing if sub-tree is perfect or not
   bool isPerfect;
   // For storing if sub-tree is complete or not
   bool isComplete;
   // Indicates size of the tree
   int size1;
   // Root of biggest complete sub-tree
   node1* rootTree;
};
// Shows helper function that returns height
// of the tree given size
int getHeight(int size1){
   return ceil(log2(size1 + 1));
}
// Shows function to return the biggest
// complete binary sub-tree
returnType findCompleteBinaryTree(struct node1* root){
   // Declaring returnType that
   // needs to be returned
   returnType rt1;
   // If root is NULL then it is considered as both
   // perfect and complete binary tree of size 0
   if (root == NULL) {
      rt1.isPerfect = true;
      rt1.isComplete = true;
      rt1.size1 = 0;
      rt1.rootTree = NULL;
      return rt1;
   }
   // Shows recursive call for left and right child
   returnType lv1 = findCompleteBinaryTree(root->left);
   returnType rv1 = findCompleteBinaryTree(root->right);
   // CASE - A
   // It has been seen that if left sub-tree is perfect and right is
   // complete and there height is also same then sub-tree root
   // is also complete binary sub-tree with size equal to
   // sum of left and right subtrees plus one for current root
   if (lv1.isPerfect == true && rv1.isComplete == true && getHeight(lv1.size1) == getHeight(rv1.size1)) {
      rt1.isComplete = true;
      // It has been seen that if right sub-tree is perfect then
      // root is also perfect
      rt1.isPerfect = (rv1.isPerfect ? true : false);
      rt1.size1 = lv1.size1 + rv1.size1 + 1;
      rt1.rootTree = root;
      return rt1;
   }
   // CASE - B
   // It has been seen if left sub-tree is complete and right is
   // also perfect and the left height is greater than height of right by one
   // then sub-tree root will be a complete binary sub-tree with the size equal to
   // sum of left and right subtrees plus one for current root.
   // But sub-tree cannot be perfect binary sub-tree.
   if (lv1.isComplete == true && rv1.isPerfect == true && getHeight(lv1.size1) == getHeight(rv1.size1) + 1) {
      rt1.isComplete = true;
      rt1.isPerfect = false;
      rt1.size1 = lv1.size1 + rv1.size1 + 1;
      rt1.rootTree = root;
      return rt1;
   }
   // CASE - C
   // Otherwise this sub-tree cannot be a complete binary tree
   // and simply return the biggest sized complete sub-tree
   // found till now in the left or right sub-trees
   rt1.isPerfect = false;
   rt1.isComplete = false;
   rt1.size1 = max(lv1.size1, rv1.size1);
   rt1.rootTree = (lv1.size1 > rv1.size1 ? lv1.rootTree :
   rv1.rootTree);
   return rt1;
}
// Shows function to print the inorder traversal of the tree
void inorderPrint(node1* root){
   if (root != NULL) {
      inorderPrint(root->left);
      cout << root->data << " ";
      inorderPrint(root->right);
   }
}
// Driver code
int main(){
   // Creating the tree
   struct node1* root = newNode(50);
   root->left = newNode(30);
   root->right = newNode(60);
   root->left->left = newNode(5);
   root->left->right = newNode(20);
   root->right->left = newNode(45);
   root->right->right = newNode(70);
   root->right->left->left = newNode(10);
   // Getting the biggest sized complete binary sub-tree
   struct returnType ans1 = findCompleteBinaryTree(root);
   cout << "Size : " << ans1.size1 << endl;
   // Printing the inorder traversal of the found sub-tree
   cout << "Inorder Traversal : ";
   inorderPrint(ans1.rootTree);
   return 0;
}

Output

Size : 4
Inorder Traversal : 10 45 60 70

Updated on: 23-Jul-2020

138 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements