Created
January 3, 2014 18:40
-
-
Save nehaljwani/8243688 to your computer and use it in GitHub Desktop.
AVLTree in Java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import java.io.*; | |
| import java.util.*; | |
| public class AVLTree { | |
| public class Node { | |
| private Node left, right, parent; | |
| private int height = 1; | |
| private int value; | |
| private Node (int val) { | |
| this.value = val; | |
| } | |
| } | |
| private int height (Node N) { | |
| if (N == null) | |
| return 0; | |
| return N.height; | |
| } | |
| private Node insert(Node node, int value) { | |
| /* 1. Perform the normal BST rotation */ | |
| if (node == null) { | |
| return(new Node(value)); | |
| } | |
| if (value < node.value) | |
| node.left = insert(node.left, value); | |
| else | |
| node.right = insert(node.right, value); | |
| /* 2. Update height of this ancestor node */ | |
| node.height = Math.max(height(node.left), height(node.right)) + 1; | |
| /* 3. Get the balance factor of this ancestor node to check whether | |
| this node became unbalanced */ | |
| int balance = getBalance(node); | |
| // If this node becomes unbalanced, then there are 4 cases | |
| // Left Left Case | |
| if (balance > 1 && value < node.left.value) | |
| return rightRotate(node); | |
| // Right Right Case | |
| if (balance < -1 && value > node.right.value) | |
| return leftRotate(node); | |
| // Left Right Case | |
| if (balance > 1 && value > node.left.value) | |
| { | |
| node.left = leftRotate(node.left); | |
| return rightRotate(node); | |
| } | |
| // Right Left Case | |
| if (balance < -1 && value < node.right.value) | |
| { | |
| node.right = rightRotate(node.right); | |
| return leftRotate(node); | |
| } | |
| /* return the (unchanged) node pointer */ | |
| return node; | |
| } | |
| private Node rightRotate(Node y) { | |
| Node x = y.left; | |
| Node T2 = x.right; | |
| // Perform rotation | |
| x.right = y; | |
| y.left = T2; | |
| // Update heights | |
| y.height = Math.max(height(y.left), height(y.right))+1; | |
| x.height = Math.max(height(x.left), height(x.right))+1; | |
| // Return new root | |
| return x; | |
| } | |
| private Node leftRotate(Node x) { | |
| Node y = x.right; | |
| Node T2 = y.left; | |
| // Perform rotation | |
| y.left = x; | |
| x.right = T2; | |
| // Update heights | |
| x.height = Math.max(height(x.left), height(x.right))+1; | |
| y.height = Math.max(height(y.left), height(y.right))+1; | |
| // Return new root | |
| return y; | |
| } | |
| // Get Balance factor of node N | |
| private int getBalance(Node N) { | |
| if (N == null) | |
| return 0; | |
| return height(N.left) - height(N.right); | |
| } | |
| public void preOrder(Node root) { | |
| if (root != null) { | |
| preOrder(root.left); | |
| System.out.printf("%d ", root.value); | |
| preOrder(root.right); | |
| } | |
| } | |
| private Node minValueNode(Node node) { | |
| Node current = node; | |
| /* loop down to find the leftmost leaf */ | |
| while (current.left != null) | |
| current = current.left; | |
| return current; | |
| } | |
| private Node deleteNode(Node root, int value) { | |
| // STEP 1: PERFORM STANDARD BST DELETE | |
| if (root == null) | |
| return root; | |
| // If the value to be deleted is smaller than the root's value, | |
| // then it lies in left subtree | |
| if ( value < root.value ) | |
| root.left = deleteNode(root.left, value); | |
| // If the value to be deleted is greater than the root's value, | |
| // then it lies in right subtree | |
| else if( value > root.value ) | |
| root.right = deleteNode(root.right, value); | |
| // if value is same as root's value, then This is the node | |
| // to be deleted | |
| else { | |
| // node with only one child or no child | |
| if( (root.left == null) || (root.right == null) ) { | |
| Node temp; | |
| if (root.left != null) | |
| temp = root.left; | |
| else | |
| temp = root.right; | |
| // No child case | |
| if(temp == null) { | |
| temp = root; | |
| root = null; | |
| } | |
| else // One child case | |
| root = temp; // Copy the contents of the non-empty child | |
| temp = null; | |
| } | |
| else { | |
| // node with two children: Get the inorder successor (smallest | |
| // in the right subtree) | |
| Node temp = minValueNode(root.right); | |
| // Copy the inorder successor's data to this node | |
| root.value = temp.value; | |
| // Delete the inorder successor | |
| root.right = deleteNode(root.right, temp.value); | |
| } | |
| } | |
| // If the tree had only one node then return | |
| if (root == null) | |
| return root; | |
| // STEP 2: UPDATE HEIGHT OF THE CURRENT NODE | |
| root.height = Math.max(height(root.left), height(root.right)) + 1; | |
| // STEP 3: GET THE BALANCE FACTOR OF THIS NODE (to check whether | |
| // this node became unbalanced) | |
| int balance = getBalance(root); | |
| // If this node becomes unbalanced, then there are 4 cases | |
| // Left Left Case | |
| if (balance > 1 && getBalance(root.left) >= 0) | |
| return rightRotate(root); | |
| // Left Right Case | |
| if (balance > 1 && getBalance(root.left) < 0) { | |
| root.left = leftRotate(root.left); | |
| return rightRotate(root); | |
| } | |
| // Right Right Case | |
| if (balance < -1 && getBalance(root.right) <= 0) | |
| return leftRotate(root); | |
| // Right Left Case | |
| if (balance < -1 && getBalance(root.right) > 0) { | |
| root.right = rightRotate(root.right); | |
| return leftRotate(root); | |
| } | |
| return root; | |
| } | |
| public void print(Node root) { | |
| if(root == null) { | |
| System.out.println("(XXXXXX)"); | |
| return; | |
| } | |
| int height = root.height, | |
| width = (int)Math.pow(2, height-1); | |
| // Preparing variables for loop. | |
| List<Node> current = new ArrayList<Node>(1), | |
| next = new ArrayList<Node>(2); | |
| current.add(root); | |
| final int maxHalfLength = 4; | |
| int elements = 1; | |
| StringBuilder sb = new StringBuilder(maxHalfLength*width); | |
| for(int i = 0; i < maxHalfLength*width; i++) | |
| sb.append(' '); | |
| String textBuffer; | |
| // Iterating through height levels. | |
| for(int i = 0; i < height; i++) { | |
| sb.setLength(maxHalfLength * ((int)Math.pow(2, height-1-i) - 1)); | |
| // Creating spacer space indicator. | |
| textBuffer = sb.toString(); | |
| // Print tree node elements | |
| for(Node n : current) { | |
| System.out.print(textBuffer); | |
| if(n == null) { | |
| System.out.print(" "); | |
| next.add(null); | |
| next.add(null); | |
| } else { | |
| System.out.printf("(%6d)", n.value); | |
| next.add(n.left); | |
| next.add(n.right); | |
| } | |
| System.out.print(textBuffer); | |
| } | |
| System.out.println(); | |
| // Print tree node extensions for next level. | |
| if(i < height - 1) { | |
| for(Node n : current) { | |
| System.out.print(textBuffer); | |
| if(n == null) | |
| System.out.print(" "); | |
| else | |
| System.out.printf("%s %s", | |
| n.left == null ? " " : "/", n.right == null ? " " : "\\"); | |
| System.out.print(textBuffer); | |
| } | |
| System.out.println(); | |
| } | |
| // Renewing indicators for next run. | |
| elements *= 2; | |
| current = next; | |
| next = new ArrayList<Node>(elements); | |
| } | |
| } | |
| public static void main(String args[]) { | |
| AVLTree t = new AVLTree(); | |
| Node root = null; | |
| while (true) { | |
| System.out.println("(1) Insert"); | |
| System.out.println("(2) Delete"); | |
| try { | |
| BufferedReader bufferRead = new BufferedReader(new InputStreamReader(System.in)); | |
| String s = bufferRead.readLine(); | |
| if (Integer.parseInt(s) == 1) { | |
| System.out.print("Value to be inserted: "); | |
| root = t.insert(root, Integer.parseInt(bufferRead.readLine())); | |
| } | |
| else if (Integer.parseInt(s) == 2) { | |
| System.out.print("Value to be deleted: "); | |
| root = t.deleteNode(root, Integer.parseInt(bufferRead.readLine())); | |
| } | |
| else { | |
| System.out.println("Invalid choice, try again!"); | |
| continue; | |
| } | |
| t.print(root); | |
| } | |
| catch(IOException e) { | |
| e.printStackTrace(); | |
| } | |
| } | |
| } | |
| } |
Author
Thanks for sharing. The preorder traversal implementation is incorrect. Please fix that.
hey thanks for sharing this code, can I just ask if it is possible to have an array representation?
@nehaljwani
Thanks a lot for this. Uhm can I ask how to get the index of each node in the AVL tree. I'm still beginner at this.
What happens if the values 3, 4, 4 are inserted in the tree?
AVL Tree Algorithm in Java from : https://atechdaily.com/posts/Heap-Sort-Algorithm-in-Cplusplus
what is the value field?
It seems this tree only works with int values?
What happens if the values 3, 4, 4 are inserted in the tree?
you can't insert same value twice
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
During the beginning I thought it might be required. Didn't end up needing it.