java 实现 avl 树

Node,java

package tree;

public class Node {

    public Class<?> clazz;

    public Integer value;

    public Node parent;

    public Node left;

    public Node right;

    public int height;

    public Node(Integer value, Node parent, Node left, Node right) {
        this.value = value;
        this.parent = parent;
        this.left = left;
        this.right = right;
    }
}

AbstractTree.java

package tree;

public abstract class AbstractTree {

    public Node root;

    protected Node rotateLeft(Node node) {
        Node temp = node.right;
        temp.parent = node.parent;

        node.right = temp.left;
        if (node.right != null) {
            node.right.parent = node;
        }

        temp.left = node;
        node.parent = temp;

        if (temp.parent == null) {
            root = temp;
        } else {
            if (temp.parent.left == node) {
                temp.parent.left = temp;
            } else {
                temp.parent.right = temp;
            }
        }

        return temp;
    }

    protected Node rotateRight(Node node) {
        Node temp = node.left;
        temp.parent = node.parent;

        node.left = temp.right;
        if (node.left != null) {
            node.left.parent = node;
        }

        temp.right = node;
        node.parent = temp;

        if (temp.parent == null) {
            root = temp;
        } else {
            if (temp.parent.left == node) {
                temp.parent.left = temp;
            } else {
                temp.parent.right = temp;
            }
        }

        return temp;
    }
}

BinarySearchTree.java

package tree;

public class BinarySearchTree extends AbstractTree {

    private int size;

    public Node insert(int e) {
        if (null == root) {
            root = new Node(e, null, null, null);
            size ++;
            return root;
        }
        Node parent = root;
        Node search = root;
        while (search != null && search.value != null) {
            parent = search;
            if (e < search.value) {
                search = search.left;
            } else {
                search = search.right;
            }
        }
        Node newNode = new Node(e, parent, null, null);
        if (parent.value > newNode.value) {
            parent.left = newNode;
        } else {
            parent.right = newNode;
        }
        size ++;
        return newNode;
    }

    public Node search(int e) {
        Node node = root;
        while (node != null && node.value != null && node.value != e) {
            if (e < node.value) {
                node = node.left;
            } else {
                node = node.right;
            }
        }
        return node;
    }

    public Node delete(int e) {
        Node delNode = search(e);
        if (null == delNode) {
            return null;
        }
        return delete(delNode);
    }

    protected Node delete(Node delNode) {
        if (delNode == null) {
            return null;
        }
        Node result;
        if (delNode.left == null) {
            result = transplant(delNode, delNode.right);
        } else if (delNode.right == null) {
            result = transplant(delNode, delNode.left);
        } else {
            Node miniNode = getMiniNode(delNode.right);
            if (miniNode.parent != delNode) {
                transplant(miniNode, miniNode.right);
                miniNode.right = delNode.right;
                miniNode.right.parent = miniNode;
            }
            transplant(delNode, miniNode);
            miniNode.left = delNode.left;
            miniNode.left.parent = miniNode;
            result = miniNode;
        }
        size--;
        return result;
    }

    protected Node getMiniNode(Node node) {
        while (node.left != null) {
            node = node.left;
        }
        return node;
    }

    private Node transplant(Node delNode, Node addNode) {
        if (delNode.parent == null) {
            this.root = addNode;
        } else if (delNode.parent.left == delNode) {
            delNode.parent.left = addNode;
        } else {
            delNode.parent.right = addNode;
        }
        if (null != addNode) {
            addNode.parent = delNode.parent;
        }
        return addNode;
    }

    public int getSize() {
        return size;
    }

}

AVLTree.java

package tree;

public class AVLTree extends BinarySearchTree {

    @Override
    public Node insert(int e) {
        var addNode = super.insert(e);
        rebalance(addNode);
        return addNode;
    }

    @Override
    public Node delete(int e) {
        var delNode = super.search(e);
        if (delNode != null) {
            var delNodeSuccess = super.delete(delNode);
            var min = delNodeSuccess.right != null ? getMiniNode(delNodeSuccess.right) : delNodeSuccess;
            recomputeHeight(min);
            rebalance(min);
        }
        return null;
    }

    private void recomputeHeight(Node node) {
        while (node != null) {
            node.height = maxHeight(node.left, node.right) + 1;
            node = node.parent;
        }
    }

    private int maxHeight(Node node1, Node node2) {
        if (node1 != null && node2 != null) {
            return node1.height > node2.height ? node1.height : node2.height;
        } else if (node1 == null) {
            return node2 != null ? node2.height : -1;
        } else if (node2 == null) {
            return node1 != null ? node1.height : -1;
        }
        return -1;
    }

    private void rebalance(Node node) {
        while (node != null) {
            var parent = node.parent;

            var leftHeight = (node.left == null) ? -1 : (node.left).height;
            var rightHeight = (node.right == null) ? -1 : (node.right).height;
            var factor = leftHeight - rightHeight;

            switch (factor) {
                case 2:
                    if (factor(node.left) >= 0) {
                        var temp = super.rotateRight(node);
                        refreshHeight(temp.right);
                        refreshHeight(temp);
                    } else {
                        var temp = super.rotateLeft(node.left);
                        refreshHeight(temp.left);
                        refreshHeight(temp);
                        node.left = temp;
                        temp = super.rotateRight(node);
                        refreshHeight(temp.right);
                        refreshHeight(temp);
                    }
                    break;
                case -2:
                    if (factor(node.right) <= 0) {
                        var temp = super.rotateLeft(node);
                        refreshHeight(temp.left);
                        refreshHeight(temp);
                    } else {
                        var temp = super.rotateRight(node.right);
                        refreshHeight(temp.right);
                        refreshHeight(temp);
                        node.right = temp;

                        temp = super.rotateLeft(node);
                        refreshHeight(temp.left);
                        refreshHeight(temp);
                    }
                    break;
                default:
                    refreshHeight(node);
                    break;
            }

            node = parent;
        }
    }

    private void refreshHeight(Node node) {
        var leftHeight = (node.left == null) ? -1 : (node.left).height;
        var rightHeight = (node.right == null) ? -1 : (node.right).height;
        node.height = 1 + Math.max(leftHeight, rightHeight);
    }

    private int factor(Node node) {
        var leftHeight = (node.left == null) ? -1 : (node.left).height;
        var rightHeight = (node.right == null) ? -1 : (node.right).height;
        return leftHeight - rightHeight;

    }

}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fanghailiang2016

扔个包子砸我一下吧~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值