Implementing an AVL tree in JAVA

前端 未结 1 1148
迷失自我
迷失自我 2021-02-11 02:10

I want to implement an AVL Tree in Java, here is what I have so far:

public class AVLNode {

  private int size; /** The size of the tree. */

  private int heig         


        
1条回答
  •  别那么骄傲
    2021-02-11 02:52

    You can try my AVL Tree which is linked here. Let me know if you have any additional questions.

    Source in case the link goes down

    package com.jwetherell.algorithms.data_structures;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
    * An AVL tree is a self-balancing binary search tree, and it was the first such
    * data structure to be invented. In an AVL tree, the heights of the two child
    * subtrees of any node differ by at most one. AVL trees are often compared with
    * red-black trees because they support the same set of operations and because
    * red-black trees also take O(log n) time for the basic operations. Because AVL
    * trees are more rigidly balanced, they are faster than red-black trees for
    * lookup intensive applications. However, red-black trees are faster for
    * insertion and removal.
    *
    * http://en.wikipedia.org/wiki/AVL_tree
    *
    * @author Justin Wetherell 
    */
    public class AVLTree> extends BinarySearchTree implements BinarySearchTree.INodeCreator {
    
        private enum Balance {
            LEFT_LEFT, LEFT_RIGHT, RIGHT_LEFT, RIGHT_RIGHT
        };
    
        /**
        * Default constructor.
        */
        public AVLTree() {
            this.creator = this;
        }
    
        /**
        * Constructor with external Node creator.
        */
        public AVLTree(INodeCreator creator) {
            super(creator);
        }
    
        /**
        * {@inheritDoc}
        */
        @Override
        protected Node addValue(T id) {
            Node nodeToReturn = super.addValue(id);
            AVLNode nodeAdded = (AVLNode) nodeToReturn;
    
            while (nodeAdded != null) {
                nodeAdded.updateHeight();
                balanceAfterInsert(nodeAdded);
                nodeAdded = (AVLNode) nodeAdded.parent;
            }
    
            return nodeToReturn;
        }
    
        /**
        * Balance the tree according to the AVL post-insert algorithm.
        *
        * @param node
        *            Root of tree to balance.
        */
        private void balanceAfterInsert(AVLNode node) {
            int balanceFactor = node.getBalanceFactor();
            if (balanceFactor > 1 || balanceFactor < -1) {
                AVLNode parent = null;
                AVLNode child = null;
                Balance balance = null;
                if (balanceFactor < 0) {
                    parent = (AVLNode) node.lesser;
                    balanceFactor = parent.getBalanceFactor();
                    if (balanceFactor < 0) {
                        child = (AVLNode) parent.lesser;
                        balance = Balance.LEFT_LEFT;
                    } else {
                        child = (AVLNode) parent.greater;
                        balance = Balance.LEFT_RIGHT;
                    }
                } else {
                    parent = (AVLNode) node.greater;
                    balanceFactor = parent.getBalanceFactor();
                    if (balanceFactor < 0) {
                        child = (AVLNode) parent.lesser;
                        balance = Balance.RIGHT_LEFT;
                    } else {
                        child = (AVLNode) parent.greater;
                        balance = Balance.RIGHT_RIGHT;
                    }
                }
    
                if (balance == Balance.LEFT_RIGHT) {
                    // Left-Right (Left rotation, right rotation)
                    rotateLeft(parent);
                    rotateRight(node);
                } else if (balance == Balance.RIGHT_LEFT) {
                    // Right-Left (Right rotation, left rotation)
                    rotateRight(parent);
                    rotateLeft(node);
                } else if (balance == Balance.LEFT_LEFT) {
                    // Left-Left (Right rotation)
                    rotateRight(node);
                } else {
                    // Right-Right (Left rotation)
                    rotateLeft(node);
                }
    
                node.updateHeight(); // New child node
                child.updateHeight(); // New child node
                parent.updateHeight(); // New Parent node
            }
        }
    
        /**
        * {@inheritDoc}
        */
        @Override
        protected Node removeValue(T value) {
            // Find node to remove
            Node nodeToRemoved = this.getNode(value);
            if (nodeToRemoved != null) {
                // Find the replacement node
                Node replacementNode = this.getReplacementNode(nodeToRemoved);
    
                // Find the parent of the replacement node to re-factor the
                // height/balance of the tree
                AVLNode nodeToRefactor = null;
                if (replacementNode != null)
                    nodeToRefactor = (AVLNode) replacementNode.parent;
                if (nodeToRefactor == null)
                    nodeToRefactor = (AVLNode) nodeToRemoved.parent;
                if (nodeToRefactor != null && nodeToRefactor.equals(nodeToRemoved))
                    nodeToRefactor = (AVLNode) replacementNode;
    
                // Replace the node
                replaceNodeWithNode(nodeToRemoved, replacementNode);
    
                // Re-balance the tree all the way up the tree
                if (nodeToRefactor != null) {
                    while (nodeToRefactor != null) {
                        nodeToRefactor.updateHeight();
                        balanceAfterDelete(nodeToRefactor);
                        nodeToRefactor = (AVLNode) nodeToRefactor.parent;
                    }
                }
            }
            return nodeToRemoved;
        }
    
        /**
        * Balance the tree according to the AVL post-delete algorithm.
        *
        * @param node
        *            Root of tree to balance.
        */
        private void balanceAfterDelete(AVLNode node) {
            int balanceFactor = node.getBalanceFactor();
            if (balanceFactor == -2 || balanceFactor == 2) {
                if (balanceFactor == -2) {
                    AVLNode ll = (AVLNode) node.lesser.lesser;
                    int lesser = (ll != null) ? ll.height : 0;
                    AVLNode lr = (AVLNode) node.lesser.greater;
                    int greater = (lr != null) ? lr.height : 0;
                    if (lesser >= greater) {
                        rotateRight(node);
                        node.updateHeight();
                        if (node.parent != null)
                            ((AVLNode) node.parent).updateHeight();
                    } else {
                        rotateLeft(node.lesser);
                        rotateRight(node);
    
                        AVLNode p = (AVLNode) node.parent;
                        if (p.lesser != null)
                            ((AVLNode) p.lesser).updateHeight();
                        if (p.greater != null)
                            ((AVLNode) p.greater).updateHeight();
                        p.updateHeight();
                    }
                } else if (balanceFactor == 2) {
                    AVLNode rr = (AVLNode) node.greater.greater;
                    int greater = (rr != null) ? rr.height : 0;
                    AVLNode rl = (AVLNode) node.greater.lesser;
                    int lesser = (rl != null) ? rl.height : 0;
                    if (greater >= lesser) {
                        rotateLeft(node);
                        node.updateHeight();
                        if (node.parent != null)
                            ((AVLNode) node.parent).updateHeight();
                    } else {
                        rotateRight(node.greater);
                        rotateLeft(node);
    
                        AVLNode p = (AVLNode) node.parent;
                        if (p.lesser != null)
                            ((AVLNode) p.lesser).updateHeight();
                        if (p.greater != null)
                            ((AVLNode) p.greater).updateHeight();
                        p.updateHeight();
                    }
                }
            }
        }
    
        /**
        * {@inheritDoc}
        */
        @Override
        protected boolean validateNode(Node node) {
            boolean bst = super.validateNode(node);
            if (!bst)
                return false;
    
            AVLNode avlNode = (AVLNode) node;
            int balanceFactor = avlNode.getBalanceFactor();
            if (balanceFactor > 1 || balanceFactor < -1) {
                return false;
            }
            if (avlNode.isLeaf()) {
                if (avlNode.height != 1)
                    return false;
            } else {
                AVLNode avlNodeLesser = (AVLNode) avlNode.lesser;
                int lesserHeight = 1;
                if (avlNodeLesser != null)
                    lesserHeight = avlNodeLesser.height;
    
                AVLNode avlNodeGreater = (AVLNode) avlNode.greater;
                int greaterHeight = 1;
                if (avlNodeGreater != null)
                    greaterHeight = avlNodeGreater.height;
    
                if (avlNode.height == (lesserHeight + 1) || avlNode.height == (greaterHeight + 1)) {
                    return true;
                } else {
                    return false;
                }
            }
    
            return true;
        }
    
        /**
        * {@inheritDoc}
        */
        @Override
        public String toString() {
            return AVLTreePrinter.getString(this);
        }
    
        /**
        * {@inheritDoc}
        */
        @Override
        public Node createNewNode(Node parent, T id) {
            return (new AVLNode(parent, id));
        }
    
        protected static class AVLNode> extends Node {
    
            protected int height = 1;
    
            /**
            * Constructor for an AVL node
            *
            * @param parent
            *            Parent of the node in the tree, can be NULL.
            * @param value
            *            Value of the node in the tree.
            */
            protected AVLNode(Node parent, T value) {
                super(parent, value);
            }
    
            /**
            * Determines is this node is a leaf (has no children).
            *
            * @return True if this node is a leaf.
            */
            protected boolean isLeaf() {
                return ((lesser == null) && (greater == null));
            }
    
            /**
            * Updates the height of this node based on it's children.
            */
            protected void updateHeight() {
                int lesserHeight = 0;
                int greaterHeight = 0;
                if (lesser != null) {
                    AVLNode lesserAVLNode = (AVLNode) lesser;
                    lesserHeight = lesserAVLNode.height;
                }
                if (greater != null) {
                    AVLNode greaterAVLNode = (AVLNode) greater;
                    greaterHeight = greaterAVLNode.height;
                }
    
                if (lesserHeight > greaterHeight) {
                    height = lesserHeight + 1;
                } else {
                    height = greaterHeight + 1;
                }
            }
    
            /**
            * Get the balance factor for this node.
            *
            * @return An integer representing the balance factor for this node. It
            *         will be negative if the lesser branch is longer than the
            *         greater branch.
            */
            protected int getBalanceFactor() {
                int lesserHeight = 0;
                int greaterHeight = 0;
                if (lesser != null) {
                    AVLNode lesserAVLNode = (AVLNode) lesser;
                    lesserHeight = lesserAVLNode.height;
                }
                if (greater != null) {
                    AVLNode greaterAVLNode = (AVLNode) greater;
                    greaterHeight = greaterAVLNode.height;
                }
                return greaterHeight - lesserHeight;
            }
    
            /**
            * {@inheritDoc}
            */
            @Override
            public String toString() {
                return "value=" + id + " height=" + height + " parent=" + ((parent != null) ? parent.id : "NULL")
                        + " lesser=" + ((lesser != null) ? lesser.id : "NULL") + " greater="
                        + ((greater != null) ? greater.id : "NULL");
            }
        }
    
        protected static class AVLTreePrinter {
    
            public static > String getString(AVLTree tree) {
                if (tree.root == null)
                    return "Tree has no nodes.";
                return getString((AVLNode) tree.root, "", true);
            }
    
            public static > String getString(AVLNode node) {
                if (node == null)
                    return "Sub-tree has no nodes.";
                return getString(node, "", true);
            }
    
            private static > String getString(AVLNode node, String prefix, boolean isTail) {
                StringBuilder builder = new StringBuilder();
    
                builder.append(prefix + (isTail ? "└── " : "├── ") + "(" + node.height + ") " + node.id + "\n");
                List> children = null;
                if (node.lesser != null || node.greater != null) {
                    children = new ArrayList>(2);
                    if (node.lesser != null)
                        children.add(node.lesser);
                    if (node.greater != null)
                        children.add(node.greater);
                }
                if (children != null) {
                    for (int i = 0; i < children.size() - 1; i++) {
                        builder.append(getString((AVLNode) children.get(i), prefix + (isTail ? "    " : "│   "), false));
                    }
                    if (children.size() >= 1) {
                        builder.append(getString((AVLNode) children.get(children.size() - 1), prefix
                                + (isTail ? "    " : "│   "), true));
                    }
                }
    
                return builder.toString();
            }
        }
    }
    

    0 讨论(0)
提交回复
热议问题