java - 如何将 BST 中的删除方法从递归切换为迭代?

标签 java algorithm recursion iteration binary-search-tree

我想知道如何将删除方法从递归切换为迭代。我的递归方法运行得非常好,但我所有使其迭代的尝试却并非如此。我哪里出了问题,该如何解决?

这是我的递归方法:

public boolean remove(E someElement) {
    return remove(root, someElement);
}
private boolean remove(Node<E> node, E dataItem) {
    if (node == null) {
        return false;
    }
    int val = dataItem.compareTo(node.data);
    if (val < 0)
        return remove(node.left, dataItem);
    else if (val > 0)
        return remove(node.right, dataItem);
    else
        return false;
}

最佳答案

由于可以获取指向变量的指针,因此在 C/C++ 中迭代执行 BST 操作比在 Java 中容易得多。

在Java中,您需要区别对待在root处找到元素的情况;在所有其他情况下,您正在考虑的节点要么位于其父节点的左侧,要么位于其父节点的右侧;因此,您可以将 C 的指针(或引用)替换为具有父节点的指针和指示当前节点位于父节点的哪一侧的 boolean 值:

public boolean remove(E someElement) {
    if (root == null) {
        return false;
    }
    int val = someElement.compareTo(root.data);
    if (val < 0) {
        return remove(root, false, someElement);
    } else if (val > 0) {
        return remove(root, true, someElement);
    } else {
        root = removeNode(root);
        return true;
    }
}

private boolean remove(Node<E> parent, boolean right, E dataItem) {
    Node<E> node = right ? parent.right : parent.left;
    if (node == null) {
        return false;
    }
    int val = dataItem.compareTo(node.data);
    if (val < 0) {
        return remove(node, false, dataItem);
    } else if (val > 0) {
        return remove(node, true, dataItem);
    } else {
        node = removeNode(node);
        if (right) {
            parent.right = node;
        } else {
            parent.left = node;
        }
        return true;
    }
}

我暂时省略了方法removeNode,现在,我们可以迭代第二个方法:

private boolean remove(Node<E> parent, boolean right, E dataItem) {
    while (true) {
        Node<E> node = right ? parent.right : parent.left;
        if (node == null) {
            return false;
        }
        int val = dataItem.compareTo(node.data);
        if (val < 0) {
            right = false;
        } else if (val > 0) {
            right = true;
        } else {
            node = removeNode(node);
            if (right) {
                parent.right = node;
            } else {
                parent.left = node;
            }
            return true;
        }
        parent = node;
    }
}

现在方法removeNode必须删除顶部节点并在删除后返回新的顶部节点。如果leftrightnull,则可以只返回另一个节点,否则,我们必须找到一个节点来替换topnode,它可以是left子树的最右边节点,也可以是right子树的leftmode节点。

private Node<E> removeNode(Node<E> parent) {
    if (parent.left == null) {
        return parent.right;
    } else if (parent.right == null) {
        return parent.left;
    }
    boolean right = random.nextBoolean();
    Node<E> node = right ? parent.right : parent.left;
    Node<E> last = removeLast(node, !right);
    if (last == null) {
        if (right) {
            node.left = parent.left;
        } else {
            node.right = parent.right;
        }
        return node;
    } else {
        last.left = parent.left;
        last.right = parent.right;
        return last;
    }
}

private Node<E> removeLast(Node<E> parent, boolean right) {
    Node<E> node = right ? parent.right : parent.left;
    if (node == null) {
        return null;
    }
    while (true) {
        Node<E> next = right ? node.right : node.left;
        if (next == null) {
            break;
        }
        parent = node;
        node = next;
    }
    if (right) {
        parent.right = node.left;
        node.left = null;
    } else {
        parent.left = node.right;
        node.right = null;
    }
    return node;
}

关于java - 如何将 BST 中的删除方法从递归切换为迭代?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58863336/

相关文章:

java - JSDAI错误: Dictionary data file is missing for schema

haskell - 这个斐波那契序列函数是递归的吗?

.net - .NET 的替代 RegEx 引擎,支持递归

c++递归调用不将项目推送到 vector

java - 从 xml 中删除子项并回车

java - 谁能解释一下这个 Java Mergesort 行为解释?

java - 以编程方式访问 Java 控制台日志

algorithm - 设计一个可以搜索具有 2 个属性的对象的数据结构

algorithm - 在计算树的直径时,为什么仅计算高度是不够的

java - 采访谜题: How to find all "bad" worker histories?