繁体   English   中英

如何使用活动标志在BST的Set ADT中实现removeAny

[英]How to implement removeAny in the Set ADT for a BST using active flags

我使用带有二进制搜索树的节点(TreeNodes)的标准方法来实现Set ADT。

我的任务是使用相同的旧节点来实现它,除了它们具有一个附加的布尔字段“ active”之外,该字段可以在节点出现时“打开”( setActive(true) )或“关闭”( setActive(false) )。除去。 这会将删除的节点保留在那里,但是当我们实现toString() ,它们将被忽略,该方法返回集合中的项。

除了removeAny() (从集合中删除任何内容,本质上是“将其关闭”)之外,我能够实现Set ADT的所有方法。 问题是我必须找到“打开”的任何节点。 为此,我必须遍历每个节点并检查一个节点是否处于活动状态。 我试图使用递归调用编写代码,但对返回的内容感到困惑。 这是我的尝试(使用Java):

public T removeAny() throws Exception {
    if (size == 0) {
        throw new Exception ("You cannot remove anything since the set is empty!");
    }

    return removeAnyHelper (root);
} 

public T removeAnyHelper (OnOffTreeNode <T> node) {

    if (node == null) {
        return root.getValue();
    }

    if (node.getActive() == true) {
        size--;
        node.setActive(false);
        return node.getValue();
    }

    removeAnyHelper (node.getLeft());

    return removeAnyHelper (node.getRight());
}

如何解决此方法? 我应该退还什么?

我尝试了一些if语句来返回removeAnyHelper (node.getLeft())removeAnyHelper (node.getRight()) ,但这没有用。

如果节点为null,则可能需要返回null(因为未删除任何内容)。

如果对左子节点的递归调用未返回null,则意味着我们删除了一个节点,需要返回它。 否则,我们需要在正确的子对象上返回调用结果。

将其转换为代码:

public T removeAnyHelper (OnOffTreeNode <T> node) {
    if (node == null) {
        return null;
    }

    if (node.getActive()) { // == true is unnecessary
        size--;
        node.setActive(false);
        return node.getValue();
    }

    T removedNode = removeAnyHelper (node.getLeft());

    if (removedNode != null)
        return removedNode;
    else
        return removeAnyHelper (node.getRight());
}

尽管我实际上不建议在BST中为节点使用活动/不活动标志- 删除节点并不是特别困难,并且可以避免拥有大量不活动节点的问题。

更一般地说,还有自平衡BST ,可以避免由于树木不平衡而导致效率降低。

好吧,我认为removeAny不是Set的正确方法,但是无论如何。

你可以(而且可能应该) removeAny通过去除前叶:

private T removeAnyHelper(OnOffTreeNode <T> node) {
    if (!present(node.getLeft() && !present(node.getRight())) {
        // no children -> this is a leaf, return
        node.setActive(false);
        return node.getValue();
    }
    // return left first, or right if left not present
    if (present(getLeft())) {
        return removeAnyHelper(getLeft());
    }
    return removeAnyHelper(getRight());
}

private boolean present(OnOffTreeNode<T> node) {
    return node != null || node.isActive();
}

请注意,您的基本removeAny方法也有一个错误,因为它不检查root的活动状态:

public T removeAny() throws NoSuchElementException {
    if (size == 0 || !root.isActive()) {
        throw new NoSuchElementException ("cant remove");
    }
    return removeAnyHelper(root);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM