AVL树实现-不存储高度

问题描述 投票:0回答:1

我目前处于AVL树插入实现的中间,在插入和回溯树时,我正在努力保持平衡因子。

实际上,我可以找到一个示例中的每个AVL实现都使用一个节点的两个子树的高度来计算平衡因子,这类似于……]

node.balance = node.right.height - node.left.height

如果您的Node类看起来像这样,那就很好了

class Node {
    int value, height;
    Node left, right;
}

尽管问题是对于此特定实现,跟踪节点的高度是“违反规则”,相反,我们只能跟踪平衡因子。所以Node类看起来像

class Node {
    int value, balance;
    Node left, right;
}

我知道保持节点的平衡因子在概念上类似于保持每个插入树的高度,但是对于我的一生,我无法弄清楚平衡因子应针对所有情况而改变的所有情况。一个特定的节点。

目前,我已经设置平衡系数,方法是为每个节点递归地调用height函数(不是最佳方法!),以确保我的旋转和常规插入是正确的。

node.balance = height(node.right) - height(node.left)

height()递归遍历树以找到通往叶子的最长路径。

并且我已经验证了旋转逻辑确实是正确的,但是当我开始编写代码以通过以+ -1增量回溯树的方式保持平衡时,代码立即变成了意大利面,因为我显然不了解有关节点平衡因子。

[如果您想查看该代码,我将其发布在下面(它有点长)。并且下面的实现也是String AVL Tree,但是想法是相同的。

感谢任何输入,谢谢!

class StringAVLNode {
    private String item;
    private int balance;
    private StringAVLNode left, right;

    // just one constructor, please
    public StringAVLNode(String str) {
        item = str;
        balance = 0;
        left = null; right = null;
    }

    public int getBalance () {
        return balance;
    }

    public void setBalance ( int bal){
        balance = bal;
    }

    public String getItem () {
        return item;
    }

    public StringAVLNode getLeft () {
        return left;
    }

    public void setLeft (StringAVLNode pt){
        left = pt;
    }

    public StringAVLNode getRight () {
        return right;
    }

    public void setRight (StringAVLNode pt){
        right = pt;
    }



    public void insert(String str) {
        root = insert(str, root);
    }


    private StringAVLNode insert(String str, StringAVLNode t) {

        // Base case - Just insert the node
        if (t == null)
            t = new StringAVLNode(str);
        else {
            int balance, leftChildBalance, rightChildBalance;
            leftChildBalance = t.getLeft() != null ? t.getLeft().getBalance() : -99;
            rightChildBalance = t.getRight() != null ? t.getRight().getBalance() : -99;

            // Perform string comparisons to determine left/right insert
            int compareResult = str.compareToIgnoreCase(t.getItem());
            if (compareResult < 0) {
                t.setLeft(insert(str, t.getLeft()));

                if (t.getRight() == null)
                    t.setBalance(t.getBalance()-1);
                else if (leftChildBalance == 0 && t.getLeft().getBalance() != 0)
                    t.setBalance(t.getBalance()-1);
                else if (leftChildBalance == -99 && t.getLeft() != null)
                    t.setBalance(t.getBalance()-1);

            }
            else if (compareResult > 0) {
                t.setRight(insert(str, t.getRight()));


                if (t.getLeft() == null)

                    t.setBalance(t.getBalance()+1);
                else if (rightChildBalance == 0 && t.getRight().getBalance() != 0)
                    t.setBalance(t.getBalance()+1);
                else if (rightChildBalance == -99 && t.getRight() != null)
                    t.setBalance(t.getBalance()+1);
            }
            balance = t.getBalance();


            // Verbosify booleans
            boolean rightImbalance = balance > 1; boolean leftImbalance = balance < -1;

            // Imbalance tree situation calls balanceTrees() to handle the rotation logic
            // ( Keeps insert() succinct )
            if (rightImbalance || leftImbalance)
                t = balanceTrees(balance, t);

        }
        return t;
    }



    // Rotation Handler
    private StringAVLNode balanceTrees(int balance, StringAVLNode t) {

        // Verbosify boolean values
        boolean rightHeavy = balance > 1; boolean leftHeavy = balance < -1;
        boolean requiresDoubleLeft = t.getRight() != null && t.getRight().getBalance() <= -1;
        boolean requiresDoubleRight = t.getLeft() != null && t.getLeft().getBalance() >= 1;

        if (rightHeavy) {

            /** Do double left rotation by right rotating the right child subtree, then
             * rotate left
             */
            if (requiresDoubleLeft) {

                t.setRight(rotateRight(t.getRight()));
                t.getRight().setBalance(0);
                t = rotateLeft(t);
                t.setBalance(0);

            }
            else {
                t = rotateLeft(t);
                t.setBalance(0);
                if (t.getLeft() != null) t.getLeft().setBalance(0);
                if (t.getRight() != null) t.getRight().setBalance(0);
            }
        }

        /** Do double right rotation by left rotating the left child subtree, then
         * rotate right
         */
        else if (leftHeavy) {
            if (requiresDoubleRight) {

                t.setLeft(rotateLeft(t.getLeft()));
                t.getLeft().setBalance(0);
                t = rotateRight(t);
                t.setBalance(0);

            }
            else {
                t = rotateRight(t);
                t.setBalance(0);
                if (t.getLeft() != null) t.getLeft().setBalance(0);
                if (t.getRight() != null) t.getRight().setBalance(0);
            }
        }
        if (t.getLeft() != null) {
            if (t.getLeft().getRight() != null && t.getLeft().getLeft() == null)
                t.getLeft().setBalance(1);
            else if (t.getLeft().getLeft() != null && t.getLeft().getRight() == null)
                t.getLeft().setBalance(-1);
            else if ((t.getLeft().getLeft() != null && t.getLeft().getRight() != null)
                    || (t.getLeft().getLeft() == null && t.getLeft().getRight() == null))
                t.getLeft().setBalance(0);
        }
        if (t.getRight() != null) {
            if (t.getRight().getRight() != null && t.getRight().getLeft() == null)
                t.getRight().setBalance(1);
            else if (t.getRight().getLeft() != null && t.getRight().getRight() == null)
                t.getRight().setBalance(-1);
            else if ((t.getRight().getLeft() != null && t.getRight().getRight() != null)
                    || (t.getRight().getLeft() == null && t.getRight().getRight() == null))
                t.getRight().setBalance(0);
        }
        return t;
    }
}

我目前处于AVL树插入实现的中间,在插入和回溯树时,我正在努力保持平衡因子。几乎每个AVL ...

java algorithm data-structures insert avl-tree
1个回答
1
投票

在以下位置以Java编写检查我的AVL树:

© www.soinside.com 2019 - 2024. All rights reserved.