/** Tree Node for Binary Search Tree * Also see: {@link BST}, {@link BSTTest} * @author Lin Chen */ public class Node { private int data; private Node left; private Node right; private Node parent; /** Initialize an empty node */ public Node() { data = 0; left = null; right = null; parent = null; } /** Initialize an node with an integer value * @param e value */ public Node(int e) { data = e; left = null; right = null; parent = null; } /** Get the node value * @return {@code int}, node value */ public int getData() { return data; } /** Get the left node * @return {@code Node}, left node of the current node */ public Node getLeft() { return left; } /** Get the right node * @return {@code Node}, right node of the current node */ public Node getRight() { return right; } /** Get the parent node * @return {@code Node}, parent node of the current node */ public Node getParent() { return parent; } /** Set node value * @param d set node value */ public void setData(int d) { data = d; } /** Set the left node * @param l set left node */ public void setLeft(Node l) { left = l; } /** Set the right node * @param r set right node */ public void setRight(Node r) { right = r; } /** Set the parent node * @param p set parent node */ public void setParent(Node p) { parent = p; } }
/** AVL tree using algorithms at geeksforgeeks * Also see: {@link Node}, {@link AVLTest} * @author Lin Chen */ public class AVL { private Node root; /** Initialize a tree */ public AVL() { root = null; } /** Return the root of the tree * @return {@code Node}, root of tree */ public Node getRoot() { return root; } /** Set a node for root * @param n node */ public void setRoot(Node n) { root = n; } /** Check if the tree is an empty tree * @return {@code bool}, tree if tree is empty; false otherwise */ public boolean isEmpty() { return (root == null); } /** Print elements in ascending ord */ public void inorderWalk() { if(root != null) printLDR(root); System.out.println(); } public void printLDR(Node n) { if(n == null) return; printLDR(n.getLeft()); System.out.printf("%5d", n.getData()); if(n.getParent() != null) System.out.printf("%10d\n", n.getParent().getData()); else System.out.printf("null\n"); printLDR(n.getRight()); } public Node rightRotate(Node y) { Node x = y.getLeft(); Node T = x.getRight(); x.setRight(y); y.setLeft(T); x.setParent(y.getParent()); y.setParent(x); T.setParent(y); return x; } public Node leftRotate(Node y) { Node x = y.getRight(); Node T = x.getLeft(); x.setLeft(y); y.setRight(T); x.setParent(y.getParent()); y.setParent(x); T.setParent(y); return x; } /** Insert an element into the tree with the algorithm in CLRS * @param e value of inserting element */ public void insert(int e) { if(search(e)) return; root = insert(root, e); } public Node insert(Node n, int e) { if(n == null) return (new Node(e)); if(e < n.getData()) { Node left = insert(n.getLeft(), e); n.setLeft(left); if(left != null) left.setParent(n); } else { Node right = insert(n.getRight(), e); n.setRight(right); if(right != null) right.setParent(n); } //LL if(isAVL(n) > 1 && e < n.getData() && e < n.getLeft().getData()) { inorderWalk(); System.out.println("Insert LL ..."+n.getData()); return rightRotate(n); } //RR if(isAVL(n) < -1 && e > n.getData() && e > n.getRight().getData()) { inorderWalk(); System.out.println("Insert RR ..."+n.getData()); return leftRotate(n); } //LR if(isAVL(n) > 1 && e < n.getData() && e > n.getLeft().getData()) { inorderWalk(); System.out.println("Insert LR ..."+n.getData()); n.setLeft(leftRotate(n.getLeft())); return rightRotate(n); } //RL if(isAVL(n) < -1 && e > n.getData() && e < n.getRight().getData()) { inorderWalk(); System.out.println("Insert RL ..."+n.getData()); n.setRight(rightRotate(n.getRight())); return leftRotate(n); } return n; } /** check if the BST is a AVL tree * @return {@code bool}, true, if the tree is a AVL tree; false, otherwise */ public int isAVL(Node n) { if(n == null) return 0; int l = getHeight(n.getLeft()); int r = getHeight(n.getRight()); return l-r; } public int height() { return getHeight(root); } public int getHeight(Node n) { if(n == null) return 0; if(n.getLeft() == null && n.getRight() == null) return 1; int l = getHeight(n.getLeft()); int r = getHeight(n.getRight()); return (l>r)?(1+l):(1+r); } public void transplant(Node u, Node v) { if(u.getParent() == null) root = v; else if(u == u.getParent().getLeft()) u.getParent().setLeft(v); else u.getParent().setRight(v); if(v != null) v.setParent(u.getParent()); } public void printNode(Node n) { if(n == null) System.out.println("Null"); else System.out.println("Node: "+n.getData()); } public void rotate() { root = rotateNode(root); } public Node rotateNode(Node n) { if(n == null) return n; n.setLeft(rotateNode(n.getLeft())); n.setRight(rotateNode(n.getRight())); //LL if(isAVL(n) > 1 && isAVL(n.getLeft()) >= 0) { System.out.println("Delete rotate LL ..."+n.getData()); return rightRotate(n); } //RR if(isAVL(n) < -1 && isAVL(n.getRight()) <= 0) { System.out.println("Delete rotate RR ..."); return leftRotate(n); } //LR if(isAVL(n) > 1 && isAVL(n.getLeft()) < 0) { System.out.println("Delete rotate LR ..."); n.setLeft(leftRotate(n.getLeft())); return rightRotate(n); } //RL if(isAVL(n) < -1 && isAVL(n.getRight()) > 0) { System.out.println("Delete rotate RL ..."); n.setRight(rightRotate(n.getRight())); return leftRotate(n); } return n; } public void delete(int e) { if(!search(e)) return; Node n = searchNode(root, e); //n has no child or only one child if(n.getLeft() == null) transplant(n, n.getRight()); else if(n.getRight() == null) transplant(n, n.getLeft()); //z has two children else { Node y = getMin(n.getRight()); if(y.getParent() != n)//y is not n's child { transplant(y, y.getRight()); y.setRight(n.getRight()); y.getRight().setParent(y); } transplant(n, y); y.setLeft(n.getLeft()); y.getLeft().setParent(y); } rotate(); } /** Search an element in tree * @param e the value of an element * @return {@code boolean}, true if the tree contains the element and false otherwise */ public boolean search(int e) { return searchNode(root, e) != null; } public Node searchNode(Node n, int e) { if(n == null) return null; if(n.getData() == e) return n; if(e < n.getData()) return searchNode(n.getLeft(), e); else return searchNode(n.getRight(), e); } public int min() { Node n = getMin(root); return n.getData(); } public Node getMin(Node n) { if(n.getLeft() == null) return n; return getMin(n.getLeft()); } }
/** Test AVL Tree * @author Lin Chen */ public class AVLTest { public static void main(String args[]) { AVL t = new AVL(); // Create tree t.insert(13); t.insert(10); t.insert(15); t.insert(5); t.insert(11); t.insert(16); t.insert(4); t.insert(6); //t.insert(14); t.insert(3); // Display tree t.inorderWalk(); // Delete t.delete(16); t.inorderWalk(); } }