仅使用一个子节点删除分支节点

时间:2014-08-06 05:32:35

标签: java recursion binary-tree root

我正在努力制作这种方法,只删除一个孩子的所有分支。例如,这个:

                    +---+
                    | 2 |
                ___ +---+ ___
              /               \
          +---+               +---+
          | 8 |               | 9 |
          +---+               +---+
         /                   /
     +---+               +---+
     | 7 |               | 6 |
     +---+               +---+
    /     \                   \
+---+     +---+               +---+
| 4 |     | 1 |               | 0 |
+---+     +---+               +---+
               \             /     \
               +---+     +---+     +---+
               | 3 |     | 4 |     | 5 |
               +---+     +---+     +---+

...变为

               +---+
               | 2 |
           ___ +---+ ___
         /               \
     +---+               +---+
     | 7 |               | 0 |
     +---+               +---+
    /     \             /     \
+---+     +---+     +---+     +---+
| 4 |     | 3 |     | 4 |     | 5 |
+---+     +---+     +---+     +---+

我并不是真的在寻找任何确切的代码解决方案,但我对如何解决此问题更感兴趣。我的想法是搜索下一个节点,看看它们是否有单个子节点。如果是这样,我将删除该节点并重新附加"之后到了一个。但是,之后的节点等也可能只有一个孩子。这就是我被困的地方。这是考虑这个问题的正确方法吗?如果没有,我该怎么做呢?

这里的代码存在严重缺陷(尚无法解决;无法获得创意):

 // post: eliminates all branches with one child
 public void tighten() {
     if (overallRoot == null || (overallRoot.left == null && overallRoot.right == null)) {
         return; // If empty or just overallRoot
     } else {
         tighten(overallRoot);
     }
 }

 // helper for tighten
 private void tighten(IntTreeNode root) {
     // checks right side first
     if (root.right.left != null && root.right.right == null) { // if next right is empty
         root.right = root.right.left;
         tighten(root.right);
     } else if (root.right.right != null && root.right.left == null) { // if next left is empty
         root.right = root.right.right;
         tighten(root.right);
     }

     // checks the left side
     if (root.left.left != null && root.left.right == null) { // if next right is empty
         root.left = root.left.left;
         tighten(root.left);
     } else if (root.left.right != null && root.left.left == null) { // if next left is empty
         root.left = root.right.right;
         tighten(root.left);
     }

     // If node with two children
     if (root.left != null && root.right != null) {
         tighten(root.left);
         tighten(root.right);
     }
 }

2 个答案:

答案 0 :(得分:0)

算法如下:

   Perform an inorder traversal of your binary tree
        For every node which has 1 child
            node->parent->child = node->child

parent->child可以是左子节点,也可以是右子节点,具体取决于当前节点的位置

答案 1 :(得分:0)

递归肯定是解决这个问题的正确方法,你已经完成了。但是,如果您递归第一个,这个问题就会变得容易多了。这样做可以让您在担心主要问题时假设子问题得到解决。这样你只需要担心root的直接孩子。这是一个实现:

private static void tighten(IntTreeNode root){
    if (root == null)
        return;

    //Recurse on both children - if either are null, returns immediately
    tighten(root.left);
    tighten(root.right);

    //Try to tighten each child. If it shouldn't be tightened, the exception is thrown.
    //Could be done using if logic, this way is fairly concise 
    //and leaves both of the helper methods for use elsewhere
    try{
        IntTreeNode n = onlyChild(root.left);
        root.left = n;   
    }catch(IllegalArgumentException ioe){}
    try{
        IntTreeNode n = onlyChild(root.right);
        root.right = n;   
    }catch(IllegalArgumentException ioe){}
}

/** Returns the number of direct children of node, or 0 if node == null */
private static int countDirectChildren(IntTreeNode node){
    if (node == null)
        return 0;
    int i = 0;
    if (node.left != null) i++;
    if (node.right != null) i++;
    return i;
}

/** Returns the single child of node. 
 *  Throws an IllegalArgumentException if node has a number of 
 *  children other than 1, or if node is null */
private static IntTreeNode onlyChild(IntTreeNode node) throws IllegalArgumentException{
    if (countDirectChildren(node) != 1) 
        throw new IllegalArgumentException(node + " doesn't have exactly one child");
    if (node.right != null) return node.right;
    else return node.left;
}