拆分二叉搜索树

时间:2017-05-03 06:45:03

标签: java algorithm data-structures binary-search-tree

给定一个BST树,我们必须根据输入(N)将树分成两个子树,其中subtree1由所有节点组成,小于或等于N,子树2由所有节点组成。大于N。

          50
     /        \
     40         60
  /    \        /
 30     45     55
                 \
                  58

输出:

       50
      /                               
     40          
   /    \         
 30     45


     60

    /

   55

     \

       58

我已经提出了以下算法,但它无法正常工作:

static Node splitTree(Node root, Node root2, int k){
    if(root == null)
        return null;

    while(root != null){
        if(root.data > k)
            root = root.left;
        else if(root.data < k)
            root = root.right;
        else
        {
            root2=root.right;
            root.right=null;
            break;
        }

    }
        return root2;


}

3 个答案:

答案 0 :(得分:6)

你不需要root2参数,因为那是函数的结果,无论如何都会覆盖传递的任何值。

分割算法通常不仅需要剪切边缘(制作两棵树),而且还要在截止树的更深层次重复此操作,因为那里可能存在应该附加的子树发生了截止。

例如,如果您的树看起来像这样:

                              16  
               +---------------+---------------+
               8                              24
       +-------+-------+               +-------+-------+
       4              12              20              28
   +---+---+       +---+---+       +---+---+       +---+---+
   2       6      10      14      18      22      26      30
 +-+-+   +-+-+   +-+-+   +-+-+   +-+-+   +-+-+   +-+-+   +-+-+
 1   3   5   7   9  11  13  15  17  19  21  23  25  27  29  31

你希望用k = 11切割,然后两棵树看起来像这样:

               8
       +-------+-------+
       4              10
   +---+---+       +---+---+
   2       6       9      11
 +-+-+   +-+-+     
 1   3   5   7      

                              16  
               +---------------+---------------+
              12                              24
               +-------+               +-------+-------+
                      14              20              28
                   +---+---+       +---+---+       +---+---+
                  13      15      18      22      26      30
                                 +-+-+   +-+-+   +-+-+   +-+-+
                                17  19  21  23  25  27  29  31

注意如何切割和更换多个边缘:16-8用16-12替换,8-12用8-10替换。这可以重复几次,并且对应于在树中找到(放置)目标值的数字侧开关(在左侧和右侧之间)。

建议代码:

static void setChild(Node node, boolean toLeft, Node child){
    // Assign child node to the indicated direction: left or right
    if (toLeft) {
        node.left = child;
    } else {
        node.right = child;
    }
}

static Node splitTree(Node root, int k){
    Node root2 = null;
    Node parent1 = null;
    Node parent2 = null;
    // Determine at which side of the root we will travel
    boolean toLeft = root != null && k < root.data;

    while (root != null) {
        while (root != null && (k < root.data) == toLeft) {
            parent1 = root;
            root = toLeft ? root.left : root.right;
        }
        setChild(parent1, toLeft, null); // Cut out the edge. root is now detached
        toLeft = !toLeft; // toggle direction
        if (root2 == null) {
            root2 = root; // This is the root of the other tree.
        } else if (parent2 != null) {
            setChild(parent2, toLeft, root); // re-attach the detached subtree
        }
        parent2 = parent1;
        parent1 = null;
    }
    return root2;
}

repl.it

上查看它

答案 1 :(得分:1)

public TreeNode[] splitBST(TreeNode root, int V) {
  if (root == null) {
      return new TreeNode[] { null, null };
  }

  if (root.val > V) {
     TreeNode[] l = splitBST(root.left, V);
     root.left = l[1];
     return new TreeNode[] { l[0], root };
  } else {
    TreeNode[] r = splitBST(root.right, V);
    root.right = r[0];
    return new TreeNode[] { root, r[1] };
  }
}

答案 2 :(得分:0)

我们可以通过递归来解决问题。

我们创建一个函数,将一对节点返回到所需的拆分树

class pair{
    node small, big;
}

我们的功能如下pair splitBST(node root, int k)

Algo:

1   //check if root is null, both trees are empty
    if (root == null) 
        return pair(null, null)

2   //check if root.data > k. In this case we know that nodes smaller than k lies in left subtree since it's given that we have BST
    //Also, root will become part of pair.big
    if (root.data > k)
        pair leftAns = splitBST(root.left, k)
        //this contains two trees-small and big where big needs to be updated as there might be nodes in left subtree that are greater than k
        root.left = leftAns.big
        leftAns.big = root
        return leftAns

3   //for all other cases, we have to scan right subtree. This time root will become part of pair.small
        pair rightAns = splitBST(root.right, k)
        root.right = rightAns.small 
        rightAns.small = root
        return rightAns

注意:在考虑递归解决方案时,总是假设我的函数在所有情况下都返回正确的答案;不要以为它是如何做到的。