数组二叉树中的删除操作

4

我知道你们可能会抱怨这个问题反复被问到。抱歉,但是我在Google/Stackoverflow/Forums等等网站上没有找到答案。

我正在用Java创建一个数组二叉树(不是搜索二叉树)。

1) 我的节点具有属性:parent(父节点)、left(左子节点)和right(右子节点)的索引号码。我的教授告诉我要这么做,但我不知道为什么,因为你可以通过公式找到父节点和子节点的索引,我希望有人能告诉我如何通过添加parent/left/right的索引来提高操作的复杂度。

2) 当你有一个指向数组中某个节点的指针时,我就无法找到删除操作的复杂度。我在考虑在删除节点时将所有节点向左移动。我认为它的时间复杂度为O(n),我不知道如何改进它。我已经读到有些人用O(log n)来实现这个操作。但他们没有说如何做到。(我很感激任何Java代码片段)。

*请记住,我正在使用Java的ArrayList。

一些代码:

public class ArrayBinaryTree<E> implements BinaryTree<E> {
    private class BTPos<T> implements Position<T> {
        private T element;
        private int parent;
        private int left;
        private int right;
        private int index;

        /** Main constructor */
        public BTPos(T element, int index, int parent, int left, int right) {
            setIndex(index);
            setElement(element);
            setParent(parent);
            setLeft(left);
            setRight(right);
        }

        /** Returns the index */
        public int getIndex() {
            return index;
        }

        /** Sets the index */
        public void setIndex(int i) {
            index = i;
        }

        /** Returns the element stored at this position */
        public T getElement() {
            return element;
        }

        /** Sets the element stored at this position */
        public void setElement(T o) {
            element = o;
        }

        /** Returns the parent */
        public int getParent() {
            return parent;
        }

        /** Sets the index */
        public void setParent(int i) {
            parent = i;
        }

        /** Returns the left */
        public int getLeft() {
            return left;
        }

        /** Sets the left */
        public void setLeft(int i) {
            left = i;
        }

        /** Returns the right */
        public int getRight() {
            return right;
        }

        /** Sets the right */
        public void setRight(int i) {
            right = i;
        }
    }
    private List<BTPos<E>> tree;
    private int size;
    private final int MAX_SIZE;

    /** Creates an empty binary tree. */
    public ArrayBinaryTree() {
        this.MAX_SIZE = 100;
        this.tree = new ArrayList<BTPos<E>>(this.MAX_SIZE);
        this.size = 0;
    }
}
2个回答

1

首先,如果您有一个固定的布局,那么仅针对索引使用公式才有效。但是,如果您没有平衡树,则在数组中浪费空间。其次,在O(log n)上解决删除问题需要平衡树(如果不是二叉搜索树 - 我不确定)。您可以使用谷歌轻松找到如何实现这一点的解释;)。


我不理解这个答案。你的意思是,我不需要存储父节点/子节点/索引值吗? - Alex
这取决于您如何在数组中存储节点。您没有分享这个信息。 - Christian Frommeyer
好的,我所做的是将数组的每个元素都指向一个BTPos对象的指针。 - Alex
是的,从给定的代码中可以清楚地看出来。但是你如何计算索引呢?你需要在数组中有一个众所周知的序列来实现这一点。 - Christian Frommeyer
你是指这些公式吗:2i + 12i + 2(i - 1)/2 - Alex
是的。只有在始终为整个树分配空间时,这些才是正确的。但是,如果树不完全平衡,则会浪费用于不存在子树的空间。 - Christian Frommeyer

1

1) 在节点中存储父/左/右索引只会浪费内存,因为您可以使用公式来实现它。

2) 如果您已经有指向要删除的节点的指针,则删除的复杂度将为O(1),您可以简单地用特殊符号标记该节点以表示它已被删除,而不是将所有节点向左移动。这样,在插入时可以重用该节点(如果您没有创建BST,则可以在删除的节点中进行任何插入)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接