Recursion 使用递归根据给定的最小值和最大值修剪二叉树

Recursion 使用递归根据给定的最小值和最大值修剪二叉树,recursion,binary-tree,Recursion,Binary Tree,正如标题所说,我必须根据给定的最小值和最大值修剪二叉树。每个节点存储一个值和一个左/右节点。我可以定义私有助手方法来解决这个问题,但是我不能调用该类的任何其他方法,也不能创建任何数据结构,例如数组、列表等 示例如下所示: overallRoot _____[50]____________________ /

正如标题所说,我必须根据给定的最小值和最大值修剪二叉树。每个节点存储一个值和一个左/右节点。我可以定义私有助手方法来解决这个问题,但是我不能调用该类的任何其他方法,也不能创建任何数据结构,例如数组、列表等

示例如下所示:

                           overallRoot
                         _____[50]____________________
                        /                             \
          __________[38]                _______________[90]
         /              \              /
    _[14]                [42]      [54]_____
   /     \                                  \
[8]       [20]                               [72]
          \                             /    \
               [26]                     [61]      [83]

trim(52, 65);
CutBranch(x,T) {
    y = T.root;
    while (y.left != x && y.right != x) {
        if (y < x) y = y.right;
        else       y = y.left;
        }
    if (y < x) y.right = Nil;
    else       y.left = Nil;
}
应返回:

overallRoot
[54]
    \
     [61]
我尝试的解决方案有三种方法:

public void trim(int min, int max) {
rootFinder(overallRoot, min, max);
}

第一个递归方法完美地找到了新的根

private void rootFinder(IntTreeNode node, int min, int max) {
if (node == null)
    return;

if (overallRoot.data < min) {
    node = overallRoot = node.right;
    rootFinder(node, min, max);

}

else if (overallRoot.data > max) {
    node = overallRoot = node.left;
    rootFinder(node, min, max);
}
else
    cutter(overallRoot, min, max);
}

感谢您的帮助。如果需要,请随时询问进一步的解释。

在处理树时,我发现最容易使用递归方法,该方法获取
节点
,并返回
节点
,这样我就可以调用该方法,通过对其调用该方法来“更新”我下面的节点

例如,在这种情况下,可以使用
节点minBound(Node)
返回该节点的子树,该子树位于下限之上。如果当前
节点
在绑定中,则递归地应用于每个子节点并返回您自己。如果当前
节点
不在绑定中,则按正确的方向返回更新的子
节点
。如果当前
节点
null
,则只需返回
null

必须为
maxBound
编写等效方法

然后只需执行
minBound(maxBound(root))
即可获得树的新根

(您可以将
minBound
maxBound
组合到一个方法中,但为了便于解释,我决定将它们分开。)

编辑:因为时间太长了,我想我应该放一个代码示例来说明我的意思

public void trim(int min, int max) {
  overallRoot = minBound(maxBound(overallRoot,max),min);
}

private IntTreeNode minBound(IntTreeNode node, int min) {
  if (node == null) // base case of our recursion
    return null;
  if (node.value < min) // we're too small, but our larger children might be in
    return minBound(node.right, min);
  // if we make it to here then we're in bounds, so update our left child
  // (our right child is bigger than us, so doesn't need to be processed)
  node.left = minBound(node.left, min);
  return node;
}

private IntTreeNode maxBound(IntTreeNode node, int max) {
  if (node == null) // base case of our recursion
    return null;
  if (node.value > max) // we're too big, but our smaller children might be in
    return maxBound(node.left, max);
  // if we make it to here then we're in bounds, so update our right child
  // (our left child is smaller than us, so doesn't need to be processed)
  node.right = maxBound(node.right, max);
  return node;
}
public void trim(int-min,int-max){
总体根=最小绑定(最大绑定(总体根,最大),最小);
}
私有IntTreeNode最小绑定(IntTreeNode节点,int最小){
if(node==null)//递归的基本情况
返回null;
if(node.valuemax)//我们太大了,但我们的小孩子可能在里面
返回maxBound(node.left,max);
//如果我们到了这里,那么我们就到了边界,所以更新我们的孩子
//(我们左边的孩子比我们小,所以不需要处理)
node.right=maxBound(node.right,max);
返回节点;
}

这假设节点x具有以下值:

  • 左(指向左子级的指针)
  • 右(指向右子级的指针)
  • 父级(指向父级的指针)
  • 您可能希望创建一个名为CutBranch的方法,该方法只需从树中删除一个节点及其所有子树。让
    T
    成为您的树,让
    T.root
    成为指向其根的指针。然后它可以这样工作:

                               overallRoot
                             _____[50]____________________
                            /                             \
              __________[38]                _______________[90]
             /              \              /
        _[14]                [42]      [54]_____
       /     \                                  \
    [8]       [20]                               [72]
              \                             /    \
                   [26]                     [61]      [83]
    
    trim(52, 65);
    
    CutBranch(x,T) {
        y = T.root;
        while (y.left != x && y.right != x) {
            if (y < x) y = y.right;
            else       y = y.left;
            }
        if (y < x) y.right = Nil;
        else       y.left = Nil;
    }
    
    CutBranch(x,T){
    y=T.根;
    while(y.left!=x&&y.right!=x){
    如果(y
    当然,这假设树中不包含具有相等值的节点,但它需要O(lgn)时间。但是,它不进行任何垃圾收集


    现在,您可以迭代节点,每次到达小于下限的节点时,可以调用其左子节点上的CutBranch,然后删除节点本身。如果节点大于你的上限,那么你可以把它拆分为正确的子并删除它。

    < P>伟大的问题,竖起大拇指,虽然我认为如果你考虑一个不同的方法,它会变得更容易。例如,对于每个节点,首先“修剪”子节点,然后“修剪”自身

  • 根据问题中的示例,以下方法假设树是BST

    public Node trim(Node root, int min, int max){
        if(root==null)
            return root;
        root.rightChild = trim (root.rightChild, min, max);
        root.leftChild = trim (root.leftChild,min,max);
    
        if(root.key>max || root.key<min){
            if(root.rightChild!=null)
                return root.rightChild;
            return root.leftChild;
        }
        return root;
    }
    
  • 该方法的调用方式如下所示

    tree.root = trim(tree.root, min, max);
    

    看起来像一个二叉搜索树!所有necros蝙蝠侠的圣母。我们中的一个人应该为此得到一枚徽章。
    tree.root = trim(tree.root, min, max);