How to determine whether a binary tree is complete?

前端 未结 16 1360
渐次进展
渐次进展 2021-01-02 19:15

A complete binary tree is defined as a binary tree in which every level, except possibly the deepest, is completely filled. At deepest level, all nodes must be as far left a

相关标签:
16条回答
  • 2021-01-02 19:40

    For a tree to be complete

    height(left) == height(right) or height(left) == 1+height(right)

        bool isComplete (struct Node* root){
        if(root==NULL)
        return true;                  // Recur for left and right subtree 
        bool flag=false;
        int option1=height(root->left);
        int option2=height(root->right);
        if(option1==option2||option1==option2+1)
        flag=true;
        return flag&&isComplete(root->left)&&isComplete(root->right);
        }
    
    0 讨论(0)
  • 2021-01-02 19:40

    The following code simply treats every possible cases. Tree height is obtained along the way to avoid another recursion.

    enum CompleteType
    {
        kNotComplete = 0,
        kComplete = 1, // Complete but not full
        kFull = 2,
        kEmpty = 3
    };
    
    CompleteType isTreeComplete(Node* node, int* height)
    {
        if (node == NULL)
        {
            *height = 0;
            return kEmpty;
        }
    
        int leftHeight, rightHeight;
    
        CompleteType leftCompleteType = isTreeComplete(node->left, &leftHeight);
        CompleteType rightCompleteType = isTreeComplete(node->right, &rightHeight);
    
        *height = max(leftHeight, rightHeight) + 1;
    
        // Straight forwardly treat all possible cases
        if (leftCompleteType == kComplete && 
            rightCompleteType == kEmpty &&
            leftHeight == rightHeight + 1)
            return kComplete;
    
        if (leftCompleteType == Full)
        {
            if (rightCompleteType == kEmpty && leftHeight == rightHeight + 1)
                return kComplete;
            if (leftHeight == rightHeight)
            {
                if (rightCompleteType == kComplete)
                    return kComplete;
                if (rightCompleteType == kFull)
                    return kFull;
            }
        }
    
        if (leftCompleteType == kEmpty && rightCompleteType == kEmpty)
            return kFull;
    
        return kNotComplete;
    }
    
    bool isTreeComplete(Node* node)
    {
        int height;
        return (isTreeComplete(node, &height) != kNotComplete);
    }
    
    0 讨论(0)
  • 2021-01-02 19:45
    int height (node* tree, int *max, int *min) {
    
      int lh = 0 , rh = 0 ;
      if ( tree == NULL )
        return 0;
      lh = height (tree->left,max,min) ;
      rh = height (tree->right,max,min) ;
      *max = ((lh>rh) ? lh : rh) + 1 ;
      *min = ((lh>rh) ? rh : lh) + 1 ;
      return *max ;
    }
    
    void isCompleteUtil (node* tree, int height, int* finish, int *complete) {
      int lh, rh ;
      if ( tree == NULL )
        return ;
      if ( height == 2 ) {
        if ( *finish ) {
          if ( !*complete )
            return;
          if ( tree->left || tree->right )
            *complete = 0 ;
          return ;
        }
        if ( tree->left == NULL && tree->right != NULL ) {
          *complete = 0 ;
          *finish = 1 ;
        }
        else if ( tree->left == NULL && tree->right == NULL )
          *finish = 1 ;
        return ;
      }
      isCompleteUtil ( tree->left, height-1, finish, complete ) ;
      isCompleteUtil ( tree->right, height-1, finish, complete ) ;
    }
    
    int isComplete (node* tree) {
      int max, min, finish=0, complete = 1 ;
      height (tree, &max, &min) ;
      if ( (max-min) >= 2 )
        return 0 ;
      isCompleteUtil (tree, max, &finish, &complete) ;
      return complete ;
    }
    
    0 讨论(0)
  • 2021-01-02 19:46

    There may be one possible algorithm which I feel would solve this problem. Consider the tree:

    Level 0:    a  
    Level 1:  b   c  
    Level 2: d e f g  
    
    • We employ breadth first traversal.

    • For each enqueued element in the queue we have to make three checks in order:

      1. If there is a single child or no child terminate; else, check 2.
      2. If there exist both children set a global flag = true.
        1. Set flags for each node in the queue as true: flag[b] = flag[c] = true.
        2. Check for each entry if they have left n right child n then set the flags or reset them to false.
        3. (Dequeue) if(queue_empty())
          compare all node flags[]... if all true global_flag = true else global_flag = false.
        4. If global_flag = true go for proceed with next level in breadth first traversal else terminate

    Advantage: entire tree may not be traversed
    Overhead: maintaining flag entries

    0 讨论(0)
  • 2021-01-02 19:47

    Similar to:

    height(t) = if (t==NULL) then 0 else 1+max(height(t.left),height(t.right))
    

    You have:

    perfect(t) = if (t==NULL) then 0 else { 
                      let h=perfect(t.left)
                      if (h != -1 && h==perfect(t.right)) then 1+h else -1
                 }
    

    Where perfect(t) returns -1 if the leaves aren't all at the same depth, or any node has only one child; otherwise, it returns the height.

    Edit: this is for "complete" = "A perfect binary tree is a full binary tree in which all leaves are at the same depth or same level.1 (This is ambiguously also called a complete binary tree.)" (Wikipedia).

    Here's a recursive check for: "A complete binary tree is a binary tree in which every level, except possibly the last, is completely filled, and all nodes are as far left as possible.". It returns (-1,false) if the tree isn't complete, otherwise (height,full) if it is, with full==true iff it's perfect.

    complete(t) = if (t==NULL) then (0,true) else { 
                      let (hl,fl)=complete(t.left)
                      let (hr,fr)=complete(t.right)                      
                      if (fl && hl==hr) then (1+h,fr)
                      else if (fr && hl==hr+1) then (1+h,false)
                      else (-1,false)
                  }
    
    0 讨论(0)
  • 2021-01-02 19:49

    Thanks for @Jonathan Graehl 's pseudo code. I've implemented it in Java. I've tested it against iterative version. It works like a charm!

    public static boolean isCompleteBinaryTreeRec(TreeNode root){
    //      Pair notComplete = new Pair(-1, false);
    //      return !isCompleteBinaryTreeSubRec(root).equalsTo(notComplete);
        return isCompleteBinaryTreeSubRec(root).height != -1;
    }
    
    public static boolean isPerfectBinaryTreeRec(TreeNode root){
        return isCompleteBinaryTreeSubRec(root).isFull;
    }
    
    public static Pair isCompleteBinaryTreeSubRec(TreeNode root){
        if(root == null){
            return new Pair(0, true);
        }
    
        Pair left = isCompleteBinaryTreeSubRec(root.left);
        Pair right = isCompleteBinaryTreeSubRec(root.right);
    
        if(left.isFull && left.height==right.height){
            return new Pair(1+left.height, right.isFull);
        }
    
        if(right.isFull && left.height==right.height+1){
            return new Pair(1+left.height, false);
        }
    
        return new Pair(-1, false);
    }
    
    private static class Pair{
        int height;         
        boolean isFull;     
    
        public Pair(int height, boolean isFull) {
            this.height = height;
            this.isFull = isFull;
        }
    
        public boolean equalsTo(Pair obj){
            return this.height==obj.height && this.isFull==obj.isFull;
        }
    }
    
    0 讨论(0)
提交回复
热议问题