【问题标题】:Removing All Leaves from a BinaryTree从二叉树中删除所有叶子
【发布时间】:2014-08-06 03:56:55
【问题描述】:

这个方法应该从二叉树(没有左右分支)中删除所有叶子,但由于某种原因,它只从二叉树中删除了一个叶子实例。这是为什么?我虽然基本情况负责通过将 parent.left 或 parent.right 设置为 null 来切断父节点的联系。如果它不是叶子,它会递归调用直到它碰到叶子。

这是我目前所拥有的:

 private IntTreeNode overallRoot; // Beginning of the chain of nodes


    // post: Removes All leaves from a tree
     public void removeLeaves() {
     if (overallRoot == null) { // If empty tree
         return;
     } else {
         removeLeaves(overallRoot);
     }

 }

 // helper for removeLeaves
 private void removeLeaves(IntTreeNode root) {       
     if (root.left != null) { // tests left root
         if (root.left.left == null && root.left.right == null) { // if next left node is leaf (base case)
             root.left = null; // delete
         } else if (root.left.left != null && root.left.right == null) { // If next right is empty
             removeLeaves(root.left.left); // only check second left
         } else if (root.left.right != null && root.left.left == null) { // If next left is empty
             removeLeaves(root.left.right); 
         } else if (root.left.left != null && root.left.right != null) { // If next left/right isn't empty
             removeLeaves(root.left.left);
             removeLeaves(root.left.right);
         }
     }

     if (root.right != null) {
         if (root.right.left == null && root.right.right == null) { // if next left node is leaf (base case)
             root.right = null; // delete
         } else if (root.right.left != null && root.right.right == null) { // If next right is empty
             removeLeaves(root.right.left); // only check second left
         } else if (root.right.right != null && root.right.left == null) { // If next left is empty
             removeLeaves(root.right.right); 
         } else if (root.right.left != null && root.right.right != null) { // If next left/right isn't empty
             removeLeaves(root.right.left);
             removeLeaves(root.right.right);
         }
     }
 }

这是单个节点类:

public class IntTreeNode {
     public int data;
     public IntTreeNode left;
     public IntTreeNode right;

     // constructs a leaf node with given data
     public IntTreeNode(int data) {
         this(data, null, null);
     }

     // constructs a branch node with given data, left subtree,
     // right subtree
     public IntTreeNode(int data, IntTreeNode left, IntTreeNode right) {
         this.data = data;
         this.left = left;
         this.right = right;
     }
}

【问题讨论】:

  • 您的问题是(1)您一次递归两个级别而不是一个级别; (2) 您永远不会处理root 本身就是叶节点的情况。我强烈建议您使用调试器逐步完成此操作,并亲自查看发生了什么问题。

标签: java recursion binary-tree


【解决方案1】:

以自下而上的方式对树进行结构修改通常更清晰:

public IntTreeNode removeLeaves(IntTreeNode root) {
    if (root == null || root.isLeaf()) {
        return null;
    }
    root.left = removeLeaves(root.left);
    root.right = removeLeaves(root.right);
    return root;
}

【讨论】:

    【解决方案2】:

    如果在你的递归调用中,而不是做

    removeLeaves(root.left.left);
    

    你会的

    removeLeaves(root.left);
    

    它应该工作。正如华莱士在评论中指出的那样,看起来您一次下降了两个级别。此外,可以通过以下方式减少代码(右树的等价物)

    if (root.left != null) { // tests left root
         if (root.left.left == null && root.left.right == null) { 
             root.left = null; // delete
         } else {
             removeLeaves(root.left);
         }
     }
    

    还要考虑到这并不能解决 root 本身就是一个休假的问题!

    【讨论】:

      【解决方案3】:

      看起来你在每次递归中都看得太远了。如果左边有叶子,调用 removeLeaves(root.left)。对右边做同样的事情。然后根据需要设置left和right为null。

      我认为这样做可以:

      public void removeLeaves(IntTreeNode root) {
      if (root != null) {
          removeLeaves(root.left);
          removeLeaves(root.right);
          root.left = null;
          root.right = null;
      }}
      

      【讨论】:

        【解决方案4】:

        这将首先搜索树的深度,然后删除遇到的叶子节点。

        公共类 RemoveLeafNode {

        public static void removeLeaves(Node root){
            if(root!=null){
                removeL(root.leftChild);
                removeL(root.rightChild);
            }
        }
        
        private static void removeL(Node node){
            if(node==null){
                return;
            }
        
            if(node.leftChild == null  && node.rightChild == null){
                node=null;//delete leaf
            }
        
            removeL(node.leftChild);
            removeL(node.rightChild);
        }
        

        }

        【讨论】:

          【解决方案5】:

          通过使用后序遍历我们可以解决这个问题(其他遍历也可以)。

          struct BinaryTreeNode* removeLeaves(struct BinaryTreeNode* root) {
              if (root != NULL)
              {
                  if (root->left == NULL && root->right == NULL)
                  {
                      free(root);
                      return NULL;
                  }
                  else
                  {
                      root->left = removeLeaves(root->left);
                      root->right = removeLeaves(root->right);
                  }
              }
              return root;
          }
          

          时间复杂度:O(n)。树中的节点数在哪里。

          【讨论】:

            猜你喜欢
            • 2018-03-04
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-12-25
            • 1970-01-01
            相关资源
            最近更新 更多