【问题标题】:Getting an object from a recursive deletion Java从递归删除Java中获取对象
【发布时间】:2014-10-18 04:26:21
【问题描述】:

我有一个包含节点的二叉搜索树。每个节点包含一个键值和数据值,节点按键排序。我正在尝试编写一种方法来从我的 BST 中删除一个对象,并提供了一个密钥。代码如下:

public Object remove(Comparable theKey) {
        return remove(theKey, rootPtr).data;
    }

public Node remove(Comparable theKey, Node node) {
    Object o;
    if(node == null)
        return node;

    if(theKey.compareTo(node.key) < 0) {
        // go to left subtree
        node.leftChild = remove(theKey, node.leftChild);
    }else if(theKey.compareTo(node.key) > 0) {
        //go to the right subtree
        node.rightChild = remove(theKey, node.rightChild);
    }else if(theKey.compareTo(node.key) == 0) {

        if(node.leftChild != null && node.rightChild != null){
            Node foundNode = findMin(node.rightChild);
            node.key = foundNode.key;
            node.data = foundNode.data;
            node.rightChild = remove(node.key, node.rightChild);
        }else{
            if(node.leftChild != null){
                node = node.leftChild;
            }else{
                node = node.rightChild;
            }
        }
    }
    numNodes--;
    return node;

 }

我想返回与 DELETED 节点关联的数据值。我遇到的问题是:在 public Object remove() 方法中,返回的值不总是根节点的数据值吗?我相信这会发生,因为从第二种方法返回的最终调用将是对 rootPtr(根指针)的引用。如果是这种情况,如何保存已删除节点中的数据?

【问题讨论】:

  • 我认为你会更好地重组这个。如果算法不是递归的,它会更清晰、更容易理解。您可以迭代地在树中搜索正确的键,存储值,删除节点并用其左或右子节点替换,然后返回您存储的值。

标签: java binary-search-tree


【解决方案1】:

最简单的解决方案似乎是添加一个输出参数而不是返回结果:

public Object remove(Comparable theKey) {
  Object[] result = new Object[1];
  rootPtr = remove(theKey, rootPtr, result);   // fix for deletion from a one-node tree
  return result[0];
}

public Node remove(Comparable theKey, Node node, Object[] result) {
  if(node == null) {
    return node;
  }
  int diff = theKey.compareTo(node.key);
  if (diff < 0) {
    node.leftChild = remove(theKey, node.leftChild, result);
  } else if (diff > 0) {
    node.rightChild = remove(theKey, node.rightChild, result);
  } else {
    result[0] = node.key;
    if (node.rightChild == null) {
      node = node.leftChild;
    } else if (node.leftChild == null) {
      node = node.rightChild;
    } else {
      Node foundNode = findMin(node.rightChild);
      node.key = foundNode.key;
      node.data = foundNode.data;
      node.rightChild = remove(node.key, node.rightChild, new Object[1]);
    }
    numNodes--;
  }
  return node;
}

如果没有重大更改,返回找到的节点将不起作用,因为返回参数用于根据需要替换节点,并且在找到的节点有两个子节点的情况下,您需要复制或插入新的节点。处理根节点被删除的情况也是一个问题。

附言我假设这不是一个“技巧问题”,你不能只返回 theKey - 毕竟它必须等于找到的密钥:)

【讨论】:

  • 如果我想返回密钥,那么我将无法返回节点,因此我的删除代码将无法正确重组树,对吗?
  • 是的。您可以在某些容器中返回两者,但这可能会增加对象创建和管理开销
【解决方案2】:

您必须返回从递归删除调用中收到的值。

p.ex:

if(theKey.compareTo(node.key) < 0) {
    // go to left subtree
    return remove(theKey, node.leftChild);
}else if ...

现在您将遍历树,直到找到正确的节点,该节点将被分配给作为要删除节点的父节点的节点,然后父节点会将其交给他的父节点,依此类推,直到根将节点返回给他的调用者。

【讨论】:

  • 这行不通(至少在不显着更改代码的情况下),因为返回值用于更新树(根据需要向上推子节点以替换删除的节点)。
猜你喜欢
  • 1970-01-01
  • 2021-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多