From c7ccfd60c3b1dbbfaefb288001d37df4e638ce04 Mon Sep 17 00:00:00 2001 From: amarmaurya-com Date: Thu, 30 Oct 2025 10:41:19 +0530 Subject: [PATCH 1/8] Implemented BST with insert and traversal methods --- src/main/java/com/thealgorithms/tree/BST.java | 278 ++++++++++++++++++ .../java/com/thealgorithms/tree/BSTTest.java | 218 ++++++++++++++ 2 files changed, 496 insertions(+) create mode 100644 src/main/java/com/thealgorithms/tree/BST.java create mode 100644 src/test/java/com/thealgorithms/tree/BSTTest.java diff --git a/src/main/java/com/thealgorithms/tree/BST.java b/src/main/java/com/thealgorithms/tree/BST.java new file mode 100644 index 000000000000..b8c4b96b4cbd --- /dev/null +++ b/src/main/java/com/thealgorithms/tree/BST.java @@ -0,0 +1,278 @@ +package com.thealgorithms.tree; + +import java.util.ArrayList; +import java.util.List; +import java.util.NoSuchElementException; + +public class BST { + + /** + * Node class represents a node in the BST. + * 0->0->0 + * 0=Nodes\ + * each node contains divided into 3 section + * Key-> Actual value, + * left-> store the address of left tree, + * Right-> store the address of right tree + */ + private static class Node { + int key; + Node left, right; + + Node(int key) { + this.key = key; + left = right = null; + } + } + + // Root of the BST + // the first of Node tree + //0-> + private Node root; + + /** Create an empty BST. */ + public BST() { + root = null; + } + + /* =========================== + * INSERT + * =========================== */ + + /** + * Insert a value into the BST. Duplicate values are ignored (no-op). + * + * @param value value to insert + */ + public void insert(int value) { + root = insertRecursive(root, value); + } + + // Helper recursive method for insertion. + private Node insertRecursive(Node node, int value) { + // If we reached a null position, create and return a new node. + if (node == null) { + return new Node(value); + } + + // If value is less, go left; if greater, go right; if equal, do nothing. + if (value < node.key) { + node.left = insertRecursive(node.left, value); + } else if (value > node.key) { + node.right = insertRecursive(node.right, value); + } // else duplicate -> ignore + + return node; // return current (possibly updated) subtree root + } + + /* =========================== + * SEARCH + * =========================== */ + + /** + * Search the BST for a value. + * + * @param value value to search + * @return true if value exists in the BST, false otherwise + */ + public boolean search(int value) { + return searchRecursive(root, value); + } + + private boolean searchRecursive(Node node, int value) { + if (node == null) { + return false; // reached leaf, not found + } + if (value == node.key) { + return true; // found exact match + } else if (value < node.key) { + return searchRecursive(node.left, value); // search left subtree + } else { + return searchRecursive(node.right, value); // search right subtree + } + } + + /* =========================== + * DELETE + * =========================== */ + + /** + * Delete a value from the BST. If the value is not present, tree remains unchanged. + * + * @param value value to delete + */ + public void delete(int value) { + root = deleteRecursive(root, value); + } + + // Helper for deletion, handles three cases: + // 1) node is a leaf -> just remove + // 2) node has one child -> replace node with child + // 3) node has two children -> replace node with successor (smallest in right subtree) + private Node deleteRecursive(Node node, int value) { + if (node == null) { + return null; // value not found + } + + if (value < node.key) { + // target is in left subtree + node.left = deleteRecursive(node.left, value); + } else if (value > node.key) { + // target is in right subtree + node.right = deleteRecursive(node.right, value); + } else { + // node.key == value -> delete this node + // Case 1 & 2: node has 0 or 1 child + if (node.left == null) { + // return right child (could be null) to replace node + return node.right; + } else if (node.right == null) { + // return left child to replace node + return node.left; + } + + // Case 3: node has two children + // Find the inorder successor (smallest in the right subtree) + Node successor = findMinNode(node.right); + // Copy successor's value to this node + node.key = successor.key; + // Delete the successor node from right subtree + node.right = deleteRecursive(node.right, successor.key); + } + + return node; + } + + /** + * Find the minimum key in the BST. + * + * @return the smallest integer key in the tree + * @throws NoSuchElementException if the tree is empty + */ + public int findMin() { + if (root == null) { + throw new NoSuchElementException("BST is empty"); + } + return findMinNode(root).key; + } + + // Helper to find node with minimum key in a subtree (leftmost node) + private Node findMinNode(Node node) { + Node current = node; + // go as far left as possible + while (current.left != null) { + current = current.left; + } + return current; + } + + /** + * Find the maximum key in the BST. + * + * the largest integer key in the tree + * NoSuchElementException if the tree is empty + */ + public int findMax() { + if (root == null) { + throw new NoSuchElementException("BST is empty"); + } + Node current = root; + // go as far right as possible + while (current.right != null) { + current = current.right; + } + return current.key; + } + + + /** + * Print inorder traversal (Left, Node, Right). + * InOrder -> Left, key, Right + */ + public void printInorder() { + System.out.print("Inorder: "); + printInorderRecursive(root); + System.out.println(); + } + + private void printInorderRecursive(Node node) { + if (node == null) return; + printInorderRecursive(node.left); // left + System.out.print(node.key + " "); // node + printInorderRecursive(node.right); // right + } + + /** + * Print preorder traversal (Node, Left, Right). + * PreOrder -> key,Left, Right + */ + public void printPreorder() { + System.out.print("Preorder: "); + printPreorderRecursive(root); + System.out.println(); + } + + private void printPreorderRecursive(Node node) { + if (node == null) return; + System.out.print(node.key + " "); // node + printPreorderRecursive(node.left); // left + printPreorderRecursive(node.right); // right + } + + /** + * Print postorder traversal (Left, Right, Node). + *PreOrder -> key,Left, Right + */ + public void printPostorder() { + System.out.print("Postorder: "); + printPostorderRecursive(root); + System.out.println(); + } + + private void printPostorderRecursive(Node node) { + if (node == null) return; + printPostorderRecursive(node.left); // left + printPostorderRecursive(node.right); // right + System.out.print(node.key + " "); // node + } + + public List inorderList() { + List result = new ArrayList<>(); + inorderToList(root, result); + return result; + } + + private void inorderToList(Node node, List out) { + if (node == null) return; + inorderToList(node.left, out); + out.add(node.key); + inorderToList(node.right, out); + } + + + public List preorderList() { + List result = new ArrayList<>(); + preorderToList(root, result); + return result; + } + + private void preorderToList(Node node, List out) { + if (node == null) return; + out.add(node.key); + preorderToList(node.left, out); + preorderToList(node.right, out); + } + + public List postorderList() { + List result = new ArrayList<>(); + postorderToList(root, result); + return result; + } + + private void postorderToList(Node node, List out) { + if (node == null) return; + postorderToList(node.left, out); + postorderToList(node.right, out); + out.add(node.key); + } +} diff --git a/src/test/java/com/thealgorithms/tree/BSTTest.java b/src/test/java/com/thealgorithms/tree/BSTTest.java new file mode 100644 index 000000000000..cff3ab6aec81 --- /dev/null +++ b/src/test/java/com/thealgorithms/tree/BSTTest.java @@ -0,0 +1,218 @@ +package com.thealgorithms.tree; + +import java.util.ArrayList; +import java.util.List; +import java.util.NoSuchElementException; + +public class BSTTest { + + private static class Node { + int key; + Node left, right; + + Node(int key) { + this.key = key; + left = right = null; + } + } + + private Node root; + + public BSTTest() { + root = null; + } + + public void insert(int value) { + root = insertRecursive(root, value); + } + + private Node insertRecursive(Node node, int value) { + if (node == null) { + return new Node(value); + } + if (value < node.key) { + node.left = insertRecursive(node.left, value); + } else if (value > node.key) { + node.right = insertRecursive(node.right, value); + } + return node; + } + + public boolean search(int value) { + return searchRecursive(root, value); + } + + private boolean searchRecursive(Node node, int value) { + if (node == null) { + return false; + } + if (value == node.key) { + return true; + } else if (value < node.key) { + return searchRecursive(node.left, value); + } else { + return searchRecursive(node.right, value); + } + } + + public void delete(int value) { + root = deleteRecursive(root, value); + } + + private Node deleteRecursive(Node node, int value) { + if (node == null) { + return null; + } + if (value < node.key) { + node.left = deleteRecursive(node.left, value); + } else if (value > node.key) { + node.right = deleteRecursive(node.right, value); + } else { + if (node.left == null) { + return node.right; + } else if (node.right == null) { + return node.left; + } + Node successor = findMinNode(node.right); + node.key = successor.key; + node.right = deleteRecursive(node.right, successor.key); + } + return node; + } + + public int findMin() { + if (root == null) { + throw new NoSuchElementException("BST is empty"); + } + return findMinNode(root).key; + } + + private Node findMinNode(Node node) { + Node current = node; + while (current.left != null) { + current = current.left; + } + return current; + } + + public int findMax() { + if (root == null) { + throw new NoSuchElementException("BST is empty"); + } + Node current = root; + while (current.right != null) { + current = current.right; + } + return current.key; + } + + public void printInorder() { + System.out.print("Inorder: "); + printInorderRecursive(root); + System.out.println(); + } + + private void printInorderRecursive(Node node) { + if (node == null) return; + printInorderRecursive(node.left); + System.out.print(node.key + " "); + printInorderRecursive(node.right); + } + + public void printPreorder() { + System.out.print("Preorder: "); + printPreorderRecursive(root); + System.out.println(); + } + + private void printPreorderRecursive(Node node) { + if (node == null) return; + System.out.print(node.key + " "); + printPreorderRecursive(node.left); + printPreorderRecursive(node.right); + } + + public void printPostorder() { + System.out.print("Postorder: "); + printPostorderRecursive(root); + System.out.println(); + } + + private void printPostorderRecursive(Node node) { + if (node == null) return; + printPostorderRecursive(node.left); + printPostorderRecursive(node.right); + System.out.print(node.key + " "); + } + + public List inorderList() { + List result = new ArrayList<>(); + inorderToList(root, result); + return result; + } + + private void inorderToList(Node node, List out) { + if (node == null) return; + inorderToList(node.left, out); + out.add(node.key); + inorderToList(node.right, out); + } + + public List preorderList() { + List result = new ArrayList<>(); + preorderToList(root, result); + return result; + } + + private void preorderToList(Node node, List out) { + if (node == null) return; + out.add(node.key); + preorderToList(node.left, out); + preorderToList(node.right, out); + } + + public List postorderList() { + List result = new ArrayList<>(); + postorderToList(root, result); + return result; + } + + private void postorderToList(Node node, List out) { + if (node == null) return; + postorderToList(node.left, out); + postorderToList(node.right, out); + out.add(node.key); + } + + public static void main(String[] args) { + BSTTest bst = new BSTTest(); + + int[] values = {50, 30, 70, 20, 40, 60, 80}; + for (int v : values) { + bst.insert(v); + } + + bst.printInorder(); + bst.printPreorder(); + bst.printPostorder(); + + System.out.println("Inorder List: " + bst.inorderList()); + System.out.println("Preorder List: " + bst.preorderList()); + System.out.println("Postorder List: " + bst.postorderList()); + + System.out.println("Search 40: " + bst.search(40)); + System.out.println("Search 99: " + bst.search(99)); + + System.out.println("Min: " + bst.findMin()); + System.out.println("Max: " + bst.findMax()); + + bst.delete(20); + System.out.println("After deleting 20 (leaf): " + bst.inorderList()); + + bst.delete(30); + System.out.println("After deleting 30 (one child): " + bst.inorderList()); + + bst.delete(50); + System.out.println("After deleting 50 (two children): " + bst.inorderList()); + } +} From f3d7f0e7e4e837370a0abc6b9e8588c5da04af59 Mon Sep 17 00:00:00 2001 From: amarmaurya-com Date: Thu, 30 Oct 2025 19:21:05 +0530 Subject: [PATCH 2/8] Added AVL tree implementation with detailed comments --- src/main/java/com/thealgorithms/tree/AVL.java | 367 ++++++++++++++++++ .../java/com/thealgorithms/tree/AVLTest.java | 245 ++++++++++++ 2 files changed, 612 insertions(+) create mode 100644 src/main/java/com/thealgorithms/tree/AVL.java create mode 100644 src/test/java/com/thealgorithms/tree/AVLTest.java diff --git a/src/main/java/com/thealgorithms/tree/AVL.java b/src/main/java/com/thealgorithms/tree/AVL.java new file mode 100644 index 000000000000..50898dc2aa02 --- /dev/null +++ b/src/main/java/com/thealgorithms/tree/AVL.java @@ -0,0 +1,367 @@ +package com.thealgorithms.tree; + +import java.util.ArrayList; +import java.util.List; +import java.util.NoSuchElementException; + +/** + * AVL (Adelson-Velsky and Landis) Tree is a self-balancing Binary Search Tree. + * Operations supported: + * - insert, delete, search + * - inorder, preorder, postorder traversal + * - findMin(), findMax() + * + * Properties: + * - For every node: |height(left) - height(right)| <= 1 + * - Maintains O(log n) time complexity for insert/delete/search + */ +public class AVL { + + /** + * Inner class to represent a node in AVL Tree + */ + private static class Node { + int key; + int height; + Node left; + Node right; + + Node(int key) { + this.key = key; + this.height = 1; // New node starts as a leaf node with height = 1 + } + } + + // Root node of the AVL Tree + private Node root; + + // Constructor + public AVL() { + root = null; + } + + /* ======================== PUBLIC METHODS ======================== */ + + /** Insert a key into the AVL Tree */ + public void insert(int key) { + root = insertRecursive(root, key); + } + + /** Delete a key from the AVL Tree */ + public void delete(int key) { + root = deleteRecursive(root, key); + } + + /** Search a key in the AVL Tree */ + public boolean search(int key) { + return searchRecursive(root, key); + } + + /** Return the smallest key in the AVL Tree */ + public int findMin() { + if (root == null) throw new NoSuchElementException("AVL Tree is empty"); + return findMinNode(root).key; + } + + /** Return the largest key in the AVL Tree */ + public int findMax() { + if (root == null) throw new NoSuchElementException("AVL Tree is empty"); + Node cur = root; + while (cur.right != null) cur = cur.right; + return cur.key; + } + + /** Print nodes in Inorder (sorted order) */ + public void printInorder() { + System.out.print("Inorder: "); + printInorderRecursive(root); + System.out.println(); + } + + /** Print nodes in Preorder (Root → Left → Right) */ + public void printPreorder() { + System.out.print("Preorder: "); + printPreorderRecursive(root); + System.out.println(); + } + + /** Print nodes in Postorder (Left → Right → Root) */ + public void printPostorder() { + System.out.print("Postorder: "); + printPostorderRecursive(root); + System.out.println(); + } + + /** Return Inorder list (useful for testing) */ + public List inorderList() { + List res = new ArrayList<>(); + inorderToList(root, res); + return res; + } + + /** Return Preorder list (useful for testing) */ + public List preorderList() { + List res = new ArrayList<>(); + preorderToList(root, res); + return res; + } + + /** Return Postorder list (useful for testing) */ + public List postorderList() { + List res = new ArrayList<>(); + postorderToList(root, res); + return res; + } + + + /** + * Recursive insert: + * 1. Insert key like a normal BST + * 2. Update height of current node + * 3. Balance the node if it became unbalanced + */ + private Node insertRecursive(Node node, int key) { + // Step 1: Perform standard BST insert + if (node == null) return new Node(key); + + if (key < node.key) + node.left = insertRecursive(node.left, key); + else if (key > node.key) + node.right = insertRecursive(node.right, key); + else + return node; // Duplicates not allowed + + // Step 2: Update height of ancestor node + updateHeight(node); + + // Step 3: Balance the node and return new root + return balanceNode(node); + } + + /** + * Recursive delete: + * 1. Perform normal BST delete + * 2. Update height of current node + * 3. Balance it if necessary + */ + private Node deleteRecursive(Node node, int key) { + if (node == null) return null; + + // Step 1: Perform BST delete + if (key < node.key) + node.left = deleteRecursive(node.left, key); + else if (key > node.key) + node.right = deleteRecursive(node.right, key); + else { + // Node found + if (node.left == null || node.right == null) { + Node temp = (node.left != null) ? node.left : node.right; + + // No child case + if (temp == null) { + node = null; + } else { + node = temp; + } + } else { + // Node with two children → get inorder successor + Node successor = findMinNode(node.right); + node.key = successor.key; + node.right = deleteRecursive(node.right, successor.key); + } + } + + // If tree had only one node + if (node == null) return null; + + // Step 2: Update height + updateHeight(node); + + // Step 3: Rebalance node + return balanceNode(node); + } + + /** Recursive search like normal BST */ + private boolean searchRecursive(Node node, int key) { + if (node == null) return false; + if (key == node.key) return true; + return key < node.key ? searchRecursive(node.left, key) : searchRecursive(node.right, key); + } + + /** Find node with minimum key */ + private Node findMinNode(Node node) { + Node cur = node; + while (cur.left != null) cur = cur.left; + return cur; + } + + /* ======================== ROTATIONS & BALANCING ======================== */ + + /** Right rotation (used in LL or LR imbalance) */ + private Node rightRotate(Node y) { + Node x = y.left; + Node T2 = x.right; + + // Perform rotation + x.right = y; + y.left = T2; + + // Update heights + updateHeight(y); + updateHeight(x); + + return x; // New root + } + + /** Left rotation (used in RR or RL imbalance) */ + private Node leftRotate(Node x) { + Node y = x.right; + Node T2 = y.left; + + // Perform rotation + y.left = x; + x.right = T2; + + // Update heights + updateHeight(x); + updateHeight(y); + + return y; // New root + } + + /** + * Balances a node by checking its balance factor: + * + * - If > 1 → left heavy + * - If < -1 → right heavy + * + * Depending on the case, we do: + * - LL → Right Rotate + * - RR → Left Rotate + * - LR → Left Rotate child + Right Rotate + * - RL → Right Rotate child + Left Rotate + */ + private Node balanceNode(Node node) { + int balance = getBalance(node); + + // Case 1: Left Left (LL) + if (balance > 1 && getBalance(node.left) >= 0) + return rightRotate(node); + + // Case 2: Left Right (LR) + if (balance > 1 && getBalance(node.left) < 0) { + node.left = leftRotate(node.left); + return rightRotate(node); + } + + // Case 3: Right Right (RR) + if (balance < -1 && getBalance(node.right) <= 0) + return leftRotate(node); + + // Case 4: Right Left (RL) + if (balance < -1 && getBalance(node.right) > 0) { + node.right = rightRotate(node.right); + return leftRotate(node); + } + + return node; // Already balanced + } + + /* ======================== HELPER FUNCTIONS ======================== */ + + /** Returns height of a node */ + private int height(Node node) { + return node == null ? 0 : node.height; + } + + /** Updates height of a node based on its children */ + private void updateHeight(Node node) { + node.height = 1 + Math.max(height(node.left), height(node.right)); + } + + /** Calculates balance factor = height(left) - height(right) */ + private int getBalance(Node node) { + return node == null ? 0 : height(node.left) - height(node.right); + } + + /* ======================== TRAVERSALS ======================== */ + + private void printInorderRecursive(Node node) { + if (node == null) return; + printInorderRecursive(node.left); + System.out.print(node.key + " "); + printInorderRecursive(node.right); + } + + private void printPreorderRecursive(Node node) { + if (node == null) return; + System.out.print(node.key + " "); + printPreorderRecursive(node.left); + printPreorderRecursive(node.right); + } + + private void printPostorderRecursive(Node node) { + if (node == null) return; + printPostorderRecursive(node.left); + printPostorderRecursive(node.right); + System.out.print(node.key + " "); + } + + private void inorderToList(Node node, List out) { + if (node == null) return; + inorderToList(node.left, out); + out.add(node.key); + inorderToList(node.right, out); + } + + private void preorderToList(Node node, List out) { + if (node == null) return; + out.add(node.key); + preorderToList(node.left, out); + preorderToList(node.right, out); + } + + private void postorderToList(Node node, List out) { + if (node == null) return; + postorderToList(node.left, out); + postorderToList(node.right, out); + out.add(node.key); + } + + public static void main(String[] args) { + AVL avl = new AVL(); + + int[] values = {30, 20, 40, 10, 25, 35, 50, 5, 15, 27, 45, 60}; + + // Insert all values one by one + for (int v : values) avl.insert(v); + + // Display traversals + avl.printInorder(); // should show sorted order + avl.printPreorder(); + avl.printPostorder(); + + // Display traversal lists + System.out.println("Inorder List: " + avl.inorderList()); + System.out.println("Preorder List: " + avl.preorderList()); + System.out.println("Postorder List: " + avl.postorderList()); + + // Search examples + System.out.println("Search 27: " + avl.search(27)); // true + System.out.println("Search 99: " + avl.search(99)); // false + + // Min and Max + System.out.println("Min: " + avl.findMin()); + System.out.println("Max: " + avl.findMax()); + + // Delete operations and show tree after each + avl.delete(10); + System.out.println("After deleting 10: " + avl.inorderList()); + + avl.delete(30); + System.out.println("After deleting 30: " + avl.inorderList()); + + avl.delete(40); + System.out.println("After deleting 40: " + avl.inorderList()); + } +} diff --git a/src/test/java/com/thealgorithms/tree/AVLTest.java b/src/test/java/com/thealgorithms/tree/AVLTest.java new file mode 100644 index 000000000000..5ef0a7acb825 --- /dev/null +++ b/src/test/java/com/thealgorithms/tree/AVLTest.java @@ -0,0 +1,245 @@ +package com.thealgorithms.tree; + +import java.util.ArrayList; +import java.util.List; +import java.util.NoSuchElementException; + +public class AVLTest { + + private static class Node { + int key; + int height; + Node left, right; + + Node(int key) { + this.key = key; + this.height = 1; // new node is initially added at leaf + this.left = this.right = null; + } + } + + private Node root; + + public AVLTest() { + root = null; + } + + public void insert(int key) { + root = insertRecursive(root, key); + } + + public void delete(int key) { + root = deleteRecursive(root, key); + } + + public boolean search(int key) { + return searchRecursive(root, key); + } + + public int findMin() { + if (root == null) throw new NoSuchElementException("AVL is empty"); + return findMinNode(root).key; + } + + public int findMax() { + if (root == null) throw new NoSuchElementException("AVL is empty"); + Node cur = root; + while (cur.right != null) cur = cur.right; + return cur.key; + } + + public void printInorder() { + System.out.print("Inorder: "); + printInorderRecursive(root); + System.out.println(); + } + + public void printPreorder() { + System.out.print("Preorder: "); + printPreorderRecursive(root); + System.out.println(); + } + + public void printPostorder() { + System.out.print("Postorder: "); + printPostorderRecursive(root); + System.out.println(); + } + + public List inorderList() { + List res = new ArrayList<>(); + inorderToList(root, res); + return res; + } + + public List preorderList() { + List res = new ArrayList<>(); + preorderToList(root, res); + return res; + } + + public List postorderList() { + List res = new ArrayList<>(); + postorderToList(root, res); + return res; + } + + /* Recursive helpers */ + + private Node insertRecursive(Node node, int key) { + if (node == null) return new Node(key); + + if (key < node.key) node.left = insertRecursive(node.left, key); + else if (key > node.key) node.right = insertRecursive(node.right, key); + else return node; // duplicates ignored + + updateHeight(node); + return balanceNode(node); + } + + private Node deleteRecursive(Node node, int key) { + if (node == null) return null; + + if (key < node.key) node.left = deleteRecursive(node.left, key); + else if (key > node.key) node.right = deleteRecursive(node.right, key); + else { + if (node.left == null || node.right == null) { + Node temp = (node.left != null) ? node.left : node.right; + if (temp == null) { + node = null; + } else { + node = temp; + } + } else { + Node successor = findMinNode(node.right); + node.key = successor.key; + node.right = deleteRecursive(node.right, successor.key); + } + } + + if (node == null) return null; + + updateHeight(node); + return balanceNode(node); + } + + private boolean searchRecursive(Node node, int key) { + if (node == null) return false; + if (key == node.key) return true; + return key < node.key ? searchRecursive(node.left, key) : searchRecursive(node.right, key); + } + + private Node findMinNode(Node node) { + Node cur = node; + while (cur.left != null) cur = cur.left; + return cur; + } + + /* Rotations & Balancing */ + + private Node rightRotate(Node y) { + Node x = y.left; + Node T2 = x.right; + + x.right = y; + y.left = T2; + + updateHeight(y); + updateHeight(x); + + return x; + } + + private Node leftRotate(Node x) { + Node y = x.right; + Node T2 = y.left; + + y.left = x; + x.right = T2; + + updateHeight(x); + updateHeight(y); + + return y; + } + + private Node balanceNode(Node node) { + int balance = getBalance(node); + + if (balance > 1 && getBalance(node.left) >= 0) { + return rightRotate(node); // LL + } + + if (balance > 1 && getBalance(node.left) < 0) { + node.left = leftRotate(node.left); // LR: left then right + return rightRotate(node); + } + + if (balance < -1 && getBalance(node.right) <= 0) { + return leftRotate(node); // RR + } + + if (balance < -1 && getBalance(node.right) > 0) { + node.right = rightRotate(node.right); // RL: right then left + return leftRotate(node); + } + + return node; + } + + private int height(Node node) { + return node == null ? 0 : node.height; + } + + private void updateHeight(Node node) { + node.height = 1 + Math.max(height(node.left), height(node.right)); + } + + private int getBalance(Node node) { + return node == null ? 0 : height(node.left) - height(node.right); + } + + /* ============ Traversal helpers ============ */ + + private void printInorderRecursive(Node node) { + if (node == null) return; + printInorderRecursive(node.left); + System.out.print(node.key + " "); + printInorderRecursive(node.right); + } + + private void printPreorderRecursive(Node node) { + if (node == null) return; + System.out.print(node.key + " "); + printPreorderRecursive(node.left); + printPreorderRecursive(node.right); + } + + private void printPostorderRecursive(Node node) { + if (node == null) return; + printPostorderRecursive(node.left); + printPostorderRecursive(node.right); + System.out.print(node.key + " "); + } + + private void inorderToList(Node node, List out) { + if (node == null) return; + inorderToList(node.left, out); + out.add(node.key); + inorderToList(node.right, out); + } + + private void preorderToList(Node node, List out) { + if (node == null) return; + out.add(node.key); + preorderToList(node.left, out); + preorderToList(node.right, out); + } + + private void postorderToList(Node node, List out) { + if (node == null) return; + postorderToList(node.left, out); + postorderToList(node.right, out); + out.add(node.key); + } +} From d0024b701ca6f4934af11354c0c384d078bf9f77 Mon Sep 17 00:00:00 2001 From: amarmaurya-com Date: Thu, 30 Oct 2025 21:17:06 +0530 Subject: [PATCH 3/8] Added AVL tree implementation with detailed comments --- src/main/java/com/thealgorithms/tree/AVL.java | 38 +++-- src/main/java/com/thealgorithms/tree/BST.java | 74 +++++++-- .../java/com/thealgorithms/tree/AVLTest.java | 24 ++- .../java/com/thealgorithms/tree/BSTTest.java | 147 +++++++++++++++--- 4 files changed, 227 insertions(+), 56 deletions(-) diff --git a/src/main/java/com/thealgorithms/tree/AVL.java b/src/main/java/com/thealgorithms/tree/AVL.java index 50898dc2aa02..b16210c28152 100644 --- a/src/main/java/com/thealgorithms/tree/AVL.java +++ b/src/main/java/com/thealgorithms/tree/AVL.java @@ -122,7 +122,9 @@ public List postorderList() { */ private Node insertRecursive(Node node, int key) { // Step 1: Perform standard BST insert - if (node == null) return new Node(key); + if (node == null) { + return new Node(key); + } if (key < node.key) node.left = insertRecursive(node.left, key); @@ -245,8 +247,8 @@ private Node balanceNode(Node node) { int balance = getBalance(node); // Case 1: Left Left (LL) - if (balance > 1 && getBalance(node.left) >= 0) - return rightRotate(node); + if (balance > 1 && getBalance(node.left) >= 0) return rightRotate(node); + // Case 2: Left Right (LR) if (balance > 1 && getBalance(node.left) < 0) { @@ -255,8 +257,8 @@ private Node balanceNode(Node node) { } // Case 3: Right Right (RR) - if (balance < -1 && getBalance(node.right) <= 0) - return leftRotate(node); + if (balance < -1 && getBalance(node.right) <= 0) return leftRotate(node); + // Case 4: Right Left (RL) if (balance < -1 && getBalance(node.right) > 0) { @@ -287,42 +289,54 @@ private int getBalance(Node node) { /* ======================== TRAVERSALS ======================== */ private void printInorderRecursive(Node node) { - if (node == null) return; + if (node == null) { + return; + } printInorderRecursive(node.left); System.out.print(node.key + " "); printInorderRecursive(node.right); } private void printPreorderRecursive(Node node) { - if (node == null) return; + if (node == null) { + return; + } System.out.print(node.key + " "); printPreorderRecursive(node.left); printPreorderRecursive(node.right); } private void printPostorderRecursive(Node node) { - if (node == null) return; + if (node == null) { + return; + } printPostorderRecursive(node.left); printPostorderRecursive(node.right); System.out.print(node.key + " "); } private void inorderToList(Node node, List out) { - if (node == null) return; + if (node == null) { + return; + } inorderToList(node.left, out); out.add(node.key); inorderToList(node.right, out); } private void preorderToList(Node node, List out) { - if (node == null) return; + if (node == null) { + return; + } out.add(node.key); preorderToList(node.left, out); preorderToList(node.right, out); } private void postorderToList(Node node, List out) { - if (node == null) return; + if (node == null) { + return; + } postorderToList(node.left, out); postorderToList(node.right, out); out.add(node.key); @@ -337,7 +351,7 @@ public static void main(String[] args) { for (int v : values) avl.insert(v); // Display traversals - avl.printInorder(); // should show sorted order + avl.printInorder(); // should show sorted order avl.printPreorder(); avl.printPostorder(); diff --git a/src/main/java/com/thealgorithms/tree/BST.java b/src/main/java/com/thealgorithms/tree/BST.java index b8c4b96b4cbd..bdfe23b3d0c3 100644 --- a/src/main/java/com/thealgorithms/tree/BST.java +++ b/src/main/java/com/thealgorithms/tree/BST.java @@ -27,7 +27,7 @@ private static class Node { // Root of the BST // the first of Node tree - //0-> + // 0-> private Node root; /** Create an empty BST. */ @@ -196,10 +196,12 @@ public void printInorder() { } private void printInorderRecursive(Node node) { - if (node == null) return; - printInorderRecursive(node.left); // left - System.out.print(node.key + " "); // node - printInorderRecursive(node.right); // right + if (node == null) { + return; + } + printInorderRecursive(node.left); // left + System.out.print(node.key + " "); // node + printInorderRecursive(node.right); // right } /** @@ -213,10 +215,12 @@ public void printPreorder() { } private void printPreorderRecursive(Node node) { - if (node == null) return; - System.out.print(node.key + " "); // node - printPreorderRecursive(node.left); // left - printPreorderRecursive(node.right); // right + if (node == null) { + return; + } + System.out.print(node.key + " "); // node + printPreorderRecursive(node.left); // left + printPreorderRecursive(node.right); // right } /** @@ -230,20 +234,24 @@ public void printPostorder() { } private void printPostorderRecursive(Node node) { - if (node == null) return; - printPostorderRecursive(node.left); // left - printPostorderRecursive(node.right); // right - System.out.print(node.key + " "); // node + if (node == null) { + return; + } + printPostorderRecursive(node.left); // left + printPostorderRecursive(node.right); // right + System.out.print(node.key + " "); // node } - public List inorderList() { + public List inorderList() { List result = new ArrayList<>(); inorderToList(root, result); return result; } private void inorderToList(Node node, List out) { - if (node == null) return; + if (node == null) { + return; + } inorderToList(node.left, out); out.add(node.key); inorderToList(node.right, out); @@ -275,4 +283,40 @@ private void postorderToList(Node node, List out) { postorderToList(node.right, out); out.add(node.key); } + + public static void main(String[] args) { + BST bst = new BST(); + + // Insert values + int[] values = {50, 30, 70, 20, 40, 60, 80}; + for (int v : values) { + bst.insert(v); + } + + bst.printInorder(); + bst.printPreorder(); + bst.printPostorder(); + + System.out.println("Inorder List: " + bst.inorderList()); + System.out.println("Preorder List: " + bst.preorderList()); + System.out.println("Postorder List: " + bst.postorderList()); + + + System.out.println("Search 40: " + bst.search(40)); // true + System.out.println("Search 99: " + bst.search(99)); // false + + + System.out.println("Min: " + bst.findMin()); // 20 + System.out.println("Max: " + bst.findMax()); // 80 + + + bst.delete(20); + System.out.println("After deleting 20 (leaf): " + bst.inorderList()); + + bst.delete(30); + System.out.println("After deleting 30 (one child): " + bst.inorderList()); + + bst.delete(50); + System.out.println("After deleting 50 (two children): " + bst.inorderList()); + } } diff --git a/src/test/java/com/thealgorithms/tree/AVLTest.java b/src/test/java/com/thealgorithms/tree/AVLTest.java index 5ef0a7acb825..514945b999d2 100644 --- a/src/test/java/com/thealgorithms/tree/AVLTest.java +++ b/src/test/java/com/thealgorithms/tree/AVLTest.java @@ -89,19 +89,31 @@ public List postorderList() { private Node insertRecursive(Node node, int key) { if (node == null) return new Node(key); - if (key < node.key) node.left = insertRecursive(node.left, key); - else if (key > node.key) node.right = insertRecursive(node.right, key); - else return node; // duplicates ignored + if (key < node.key) { + node.left = insertRecursive(node.left, key); + } + else if (key > node.key) { + node.right = insertRecursive(node.right, key); + } + else { + return node; // duplicates ignored + } updateHeight(node); return balanceNode(node); } private Node deleteRecursive(Node node, int key) { - if (node == null) return null; + if (node == null) { + return null; + } - if (key < node.key) node.left = deleteRecursive(node.left, key); - else if (key > node.key) node.right = deleteRecursive(node.right, key); + if (key < node.key) { + node.left = deleteRecursive(node.left, key); + } + else if (key > node.key) { + node.right = deleteRecursive(node.right, key); + } else { if (node.left == null || node.right == null) { Node temp = (node.left != null) ? node.left : node.right; diff --git a/src/test/java/com/thealgorithms/tree/BSTTest.java b/src/test/java/com/thealgorithms/tree/BSTTest.java index cff3ab6aec81..8a460487a087 100644 --- a/src/test/java/com/thealgorithms/tree/BSTTest.java +++ b/src/test/java/com/thealgorithms/tree/BSTTest.java @@ -6,6 +6,15 @@ public class BSTTest { + /** + * Node class represents a node in the BST. + * 0->0->0 + * 0=Nodes\ + * each node contains divided into 3 section + * Key-> Actual value, + * left-> store the address of left tree, + * Right-> store the address of right tree + */ private static class Node { int key; Node left, right; @@ -16,70 +25,128 @@ private static class Node { } } + // Root of the BST + // the first of Node tree + //0-> private Node root; + /** Create an empty BST. */ public BSTTest() { root = null; } + /* =========================== + * INSERT + * =========================== */ + + /** + * Insert a value into the BST. Duplicate values are ignored (no-op). + * + * @param value value to insert + */ public void insert(int value) { root = insertRecursive(root, value); } + // Helper recursive method for insertion. private Node insertRecursive(Node node, int value) { + // If we reached a null position, create and return a new node. if (node == null) { return new Node(value); } + + // If value is less, go left; if greater, go right; if equal, do nothing. if (value < node.key) { node.left = insertRecursive(node.left, value); } else if (value > node.key) { node.right = insertRecursive(node.right, value); - } - return node; + } // else duplicate -> ignore + + return node; // return current (possibly updated) subtree root } + /* =========================== + * SEARCH + * =========================== */ + + /** + * Search the BST for a value. + * + */ public boolean search(int value) { return searchRecursive(root, value); } private boolean searchRecursive(Node node, int value) { if (node == null) { - return false; + return false; // reached leaf, not found } if (value == node.key) { - return true; + return true; // found exact match } else if (value < node.key) { - return searchRecursive(node.left, value); + return searchRecursive(node.left, value); // search left subtree } else { - return searchRecursive(node.right, value); + return searchRecursive(node.right, value); // search right subtree } } + /* =========================== + * DELETE + * =========================== */ + + /** + * Delete a value from the BST. If the value is not present, tree remains unchanged. + * + * @param value value to delete + */ public void delete(int value) { root = deleteRecursive(root, value); } + // Helper for deletion, handles three cases: + // 1) node is a leaf -> just remove + // 2) node has one child -> replace node with child + // 3) node has two children -> replace node with successor (smallest in right subtree) private Node deleteRecursive(Node node, int value) { if (node == null) { - return null; + return null; // value not found } + if (value < node.key) { + // target is in left subtree node.left = deleteRecursive(node.left, value); } else if (value > node.key) { + // target is in right subtree node.right = deleteRecursive(node.right, value); } else { + // node.key == value -> delete this node + // Case 1 & 2: node has 0 or 1 child if (node.left == null) { + // return right child (could be null) to replace node return node.right; } else if (node.right == null) { + // return left child to replace node return node.left; } + + // Case 3: node has two children + // Find the inorder successor (smallest in the right subtree) Node successor = findMinNode(node.right); + // Copy successor's value to this node node.key = successor.key; + // Delete the successor node from right subtree node.right = deleteRecursive(node.right, successor.key); } + return node; } + /** + * Find the minimum key in the BST. + * + * @return the smallest integer key in the tree + * @throws NoSuchElementException if the tree is empty + */ public int findMin() { if (root == null) { throw new NoSuchElementException("BST is empty"); @@ -87,25 +154,39 @@ public int findMin() { return findMinNode(root).key; } + // Helper to find node with minimum key in a subtree (leftmost node) private Node findMinNode(Node node) { Node current = node; + // go as far left as possible while (current.left != null) { current = current.left; } return current; } + /** + * Find the maximum key in the BST. + * + * the largest integer key in the tree + * NoSuchElementException if the tree is empty + */ public int findMax() { if (root == null) { throw new NoSuchElementException("BST is empty"); } Node current = root; + // go as far right as possible while (current.right != null) { current = current.right; } return current.key; } + + /** + * Print inorder traversal (Left, Node, Right). + * InOrder -> Left, key, Right + */ public void printInorder() { System.out.print("Inorder: "); printInorderRecursive(root); @@ -113,12 +194,18 @@ public void printInorder() { } private void printInorderRecursive(Node node) { - if (node == null) return; - printInorderRecursive(node.left); - System.out.print(node.key + " "); - printInorderRecursive(node.right); + if (node == null) { + return; + } + printInorderRecursive(node.left); // left + System.out.print(node.key + " "); // node + printInorderRecursive(node.right); // right } + /** + * Print preorder traversal (Node, Left, Right). + * PreOrder -> key,Left, Right + */ public void printPreorder() { System.out.print("Preorder: "); printPreorderRecursive(root); @@ -126,12 +213,18 @@ public void printPreorder() { } private void printPreorderRecursive(Node node) { - if (node == null) return; - System.out.print(node.key + " "); - printPreorderRecursive(node.left); - printPreorderRecursive(node.right); + if (node == null) { + return; + } + System.out.print(node.key + " "); // node + printPreorderRecursive(node.left); // left + printPreorderRecursive(node.right); // right } + /** + * Print postorder traversal (Left, Right, Node). + *PreOrder -> key,Left, Right + */ public void printPostorder() { System.out.print("Postorder: "); printPostorderRecursive(root); @@ -139,10 +232,12 @@ public void printPostorder() { } private void printPostorderRecursive(Node node) { - if (node == null) return; - printPostorderRecursive(node.left); - printPostorderRecursive(node.right); - System.out.print(node.key + " "); + if (node == null) { + return; + } + printPostorderRecursive(node.left); // left + printPostorderRecursive(node.right); // right + System.out.print(node.key + " "); // node } public List inorderList() { @@ -152,12 +247,15 @@ public List inorderList() { } private void inorderToList(Node node, List out) { - if (node == null) return; + if (node == null) { + return; + } inorderToList(node.left, out); out.add(node.key); inorderToList(node.right, out); } + public List preorderList() { List result = new ArrayList<>(); preorderToList(root, result); @@ -165,7 +263,9 @@ public List preorderList() { } private void preorderToList(Node node, List out) { - if (node == null) return; + if (node == null) { + return; + } out.add(node.key); preorderToList(node.left, out); preorderToList(node.right, out); @@ -178,12 +278,13 @@ public List postorderList() { } private void postorderToList(Node node, List out) { - if (node == null) return; + if (node == null) { + return; + } postorderToList(node.left, out); postorderToList(node.right, out); out.add(node.key); } - public static void main(String[] args) { BSTTest bst = new BSTTest(); From 406ca5e310e100f55470f2ede2b10bd8c68138a0 Mon Sep 17 00:00:00 2001 From: amarmaurya-com Date: Thu, 30 Oct 2025 21:52:28 +0530 Subject: [PATCH 4/8] Added AVL tree implementation with detailed comments --- src/main/java/com/thealgorithms/tree/AVL.java | 3 --- src/main/java/com/thealgorithms/tree/BST.java | 7 +----- .../java/com/thealgorithms/tree/AVLTest.java | 12 ++++------ .../java/com/thealgorithms/tree/BSTTest.java | 22 +++++++++---------- 4 files changed, 15 insertions(+), 29 deletions(-) diff --git a/src/main/java/com/thealgorithms/tree/AVL.java b/src/main/java/com/thealgorithms/tree/AVL.java index b16210c28152..73cc5ccb4d9f 100644 --- a/src/main/java/com/thealgorithms/tree/AVL.java +++ b/src/main/java/com/thealgorithms/tree/AVL.java @@ -113,7 +113,6 @@ public List postorderList() { return res; } - /** * Recursive insert: * 1. Insert key like a normal BST @@ -249,7 +248,6 @@ private Node balanceNode(Node node) { // Case 1: Left Left (LL) if (balance > 1 && getBalance(node.left) >= 0) return rightRotate(node); - // Case 2: Left Right (LR) if (balance > 1 && getBalance(node.left) < 0) { node.left = leftRotate(node.left); @@ -259,7 +257,6 @@ private Node balanceNode(Node node) { // Case 3: Right Right (RR) if (balance < -1 && getBalance(node.right) <= 0) return leftRotate(node); - // Case 4: Right Left (RL) if (balance < -1 && getBalance(node.right) > 0) { node.right = rightRotate(node.right); diff --git a/src/main/java/com/thealgorithms/tree/BST.java b/src/main/java/com/thealgorithms/tree/BST.java index bdfe23b3d0c3..b42d4b49b182 100644 --- a/src/main/java/com/thealgorithms/tree/BST.java +++ b/src/main/java/com/thealgorithms/tree/BST.java @@ -184,7 +184,6 @@ public int findMax() { return current.key; } - /** * Print inorder traversal (Left, Node, Right). * InOrder -> Left, key, Right @@ -242,7 +241,7 @@ private void printPostorderRecursive(Node node) { System.out.print(node.key + " "); // node } - public List inorderList() { + public List inorderList() { List result = new ArrayList<>(); inorderToList(root, result); return result; @@ -257,7 +256,6 @@ private void inorderToList(Node node, List out) { inorderToList(node.right, out); } - public List preorderList() { List result = new ArrayList<>(); preorderToList(root, result); @@ -301,15 +299,12 @@ public static void main(String[] args) { System.out.println("Preorder List: " + bst.preorderList()); System.out.println("Postorder List: " + bst.postorderList()); - System.out.println("Search 40: " + bst.search(40)); // true System.out.println("Search 99: " + bst.search(99)); // false - System.out.println("Min: " + bst.findMin()); // 20 System.out.println("Max: " + bst.findMax()); // 80 - bst.delete(20); System.out.println("After deleting 20 (leaf): " + bst.inorderList()); diff --git a/src/test/java/com/thealgorithms/tree/AVLTest.java b/src/test/java/com/thealgorithms/tree/AVLTest.java index 514945b999d2..e53a710514f5 100644 --- a/src/test/java/com/thealgorithms/tree/AVLTest.java +++ b/src/test/java/com/thealgorithms/tree/AVLTest.java @@ -91,11 +91,9 @@ private Node insertRecursive(Node node, int key) { if (key < node.key) { node.left = insertRecursive(node.left, key); - } - else if (key > node.key) { + } else if (key > node.key) { node.right = insertRecursive(node.right, key); - } - else { + } else { return node; // duplicates ignored } @@ -110,11 +108,9 @@ private Node deleteRecursive(Node node, int key) { if (key < node.key) { node.left = deleteRecursive(node.left, key); - } - else if (key > node.key) { + } else if (key > node.key) { node.right = deleteRecursive(node.right, key); - } - else { + } else { if (node.left == null || node.right == null) { Node temp = (node.left != null) ? node.left : node.right; if (temp == null) { diff --git a/src/test/java/com/thealgorithms/tree/BSTTest.java b/src/test/java/com/thealgorithms/tree/BSTTest.java index 8a460487a087..c5af9cd16c74 100644 --- a/src/test/java/com/thealgorithms/tree/BSTTest.java +++ b/src/test/java/com/thealgorithms/tree/BSTTest.java @@ -27,7 +27,7 @@ private static class Node { // Root of the BST // the first of Node tree - //0-> + // 0-> private Node root; /** Create an empty BST. */ @@ -182,7 +182,6 @@ public int findMax() { return current.key; } - /** * Print inorder traversal (Left, Node, Right). * InOrder -> Left, key, Right @@ -197,9 +196,9 @@ private void printInorderRecursive(Node node) { if (node == null) { return; } - printInorderRecursive(node.left); // left - System.out.print(node.key + " "); // node - printInorderRecursive(node.right); // right + printInorderRecursive(node.left); // left + System.out.print(node.key + " "); // node + printInorderRecursive(node.right); // right } /** @@ -216,9 +215,9 @@ private void printPreorderRecursive(Node node) { if (node == null) { return; } - System.out.print(node.key + " "); // node - printPreorderRecursive(node.left); // left - printPreorderRecursive(node.right); // right + System.out.print(node.key + " "); // node + printPreorderRecursive(node.left); // left + printPreorderRecursive(node.right); // right } /** @@ -235,9 +234,9 @@ private void printPostorderRecursive(Node node) { if (node == null) { return; } - printPostorderRecursive(node.left); // left - printPostorderRecursive(node.right); // right - System.out.print(node.key + " "); // node + printPostorderRecursive(node.left); // left + printPostorderRecursive(node.right); // right + System.out.print(node.key + " "); // node } public List inorderList() { @@ -255,7 +254,6 @@ private void inorderToList(Node node, List out) { inorderToList(node.right, out); } - public List preorderList() { List result = new ArrayList<>(); preorderToList(root, result); From 3541571cab846140ce7248564f021f91773b8115 Mon Sep 17 00:00:00 2001 From: amarmaurya-com Date: Thu, 30 Oct 2025 22:05:16 +0530 Subject: [PATCH 5/8] Added AVL tree implementation with detailed comments --- src/test/java/com/thealgorithms/tree/AVLTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/thealgorithms/tree/AVLTest.java b/src/test/java/com/thealgorithms/tree/AVLTest.java index e53a710514f5..d135e40fbf27 100644 --- a/src/test/java/com/thealgorithms/tree/AVLTest.java +++ b/src/test/java/com/thealgorithms/tree/AVLTest.java @@ -95,7 +95,7 @@ private Node insertRecursive(Node node, int key) { node.right = insertRecursive(node.right, key); } else { return node; // duplicates ignored - } + } updateHeight(node); return balanceNode(node); From 646b998efd3aaabb3c1978bdc657c5fc649111fd Mon Sep 17 00:00:00 2001 From: amarmaurya-com Date: Thu, 30 Oct 2025 23:25:49 +0530 Subject: [PATCH 6/8] Added AVL tree implementation with detailed comments --- src/main/java/com/thealgorithms/tree/AVL.java | 212 ++++++------------ src/main/java/com/thealgorithms/tree/BST.java | 171 +++++--------- .../java/com/thealgorithms/tree/AVLTest.java | 135 ++++++++--- .../java/com/thealgorithms/tree/BSTTest.java | 126 ++--------- 4 files changed, 250 insertions(+), 394 deletions(-) diff --git a/src/main/java/com/thealgorithms/tree/AVL.java b/src/main/java/com/thealgorithms/tree/AVL.java index 73cc5ccb4d9f..60463c7f7c12 100644 --- a/src/main/java/com/thealgorithms/tree/AVL.java +++ b/src/main/java/com/thealgorithms/tree/AVL.java @@ -4,22 +4,8 @@ import java.util.List; import java.util.NoSuchElementException; -/** - * AVL (Adelson-Velsky and Landis) Tree is a self-balancing Binary Search Tree. - * Operations supported: - * - insert, delete, search - * - inorder, preorder, postorder traversal - * - findMin(), findMax() - * - * Properties: - * - For every node: |height(left) - height(right)| <= 1 - * - Maintains O(log n) time complexity for insert/delete/search - */ public class AVL { - /** - * Inner class to represent a node in AVL Tree - */ private static class Node { int key; int height; @@ -28,263 +14,230 @@ private static class Node { Node(int key) { this.key = key; - this.height = 1; // New node starts as a leaf node with height = 1 + left = right = null; + this.height = 1; } } - // Root node of the AVL Tree private Node root; - // Constructor public AVL() { root = null; } - /* ======================== PUBLIC METHODS ======================== */ - - /** Insert a key into the AVL Tree */ public void insert(int key) { root = insertRecursive(root, key); } - /** Delete a key from the AVL Tree */ public void delete(int key) { root = deleteRecursive(root, key); } - /** Search a key in the AVL Tree */ public boolean search(int key) { return searchRecursive(root, key); } - /** Return the smallest key in the AVL Tree */ public int findMin() { - if (root == null) throw new NoSuchElementException("AVL Tree is empty"); + if (root == null) { + throw new NoSuchElementException("AVL Tree is empty"); + } return findMinNode(root).key; } - /** Return the largest key in the AVL Tree */ public int findMax() { - if (root == null) throw new NoSuchElementException("AVL Tree is empty"); + if (root == null) { + throw new NoSuchElementException("AVL Tree is empty"); + } Node cur = root; - while (cur.right != null) cur = cur.right; + while (cur.right != null) { + cur = cur.right; + } return cur.key; } - /** Print nodes in Inorder (sorted order) */ public void printInorder() { System.out.print("Inorder: "); printInorderRecursive(root); System.out.println(); } - /** Print nodes in Preorder (Root → Left → Right) */ public void printPreorder() { System.out.print("Preorder: "); printPreorderRecursive(root); System.out.println(); } - /** Print nodes in Postorder (Left → Right → Root) */ public void printPostorder() { System.out.print("Postorder: "); printPostorderRecursive(root); System.out.println(); } - /** Return Inorder list (useful for testing) */ public List inorderList() { List res = new ArrayList<>(); inorderToList(root, res); return res; } - /** Return Preorder list (useful for testing) */ public List preorderList() { List res = new ArrayList<>(); preorderToList(root, res); return res; } - /** Return Postorder list (useful for testing) */ public List postorderList() { List res = new ArrayList<>(); postorderToList(root, res); return res; } - /** - * Recursive insert: - * 1. Insert key like a normal BST - * 2. Update height of current node - * 3. Balance the node if it became unbalanced - */ private Node insertRecursive(Node node, int key) { - // Step 1: Perform standard BST insert if (node == null) { return new Node(key); } - if (key < node.key) + if (key < node.key) { node.left = insertRecursive(node.left, key); - else if (key > node.key) + } else if (key > node.key) { node.right = insertRecursive(node.right, key); - else - return node; // Duplicates not allowed + } else { + return node; + } - // Step 2: Update height of ancestor node updateHeight(node); - - // Step 3: Balance the node and return new root return balanceNode(node); } - /** - * Recursive delete: - * 1. Perform normal BST delete - * 2. Update height of current node - * 3. Balance it if necessary - */ private Node deleteRecursive(Node node, int key) { - if (node == null) return null; + if (node == null) { + return null; + } - // Step 1: Perform BST delete - if (key < node.key) + if (key < node.key) { node.left = deleteRecursive(node.left, key); - else if (key > node.key) + } else if (key > node.key) { node.right = deleteRecursive(node.right, key); - else { - // Node found + } else { if (node.left == null || node.right == null) { - Node temp = (node.left != null) ? node.left : node.right; + Node temp = null; + if (node.left != null) { + temp = node.left; + } else { + temp = node.right; + } - // No child case if (temp == null) { node = null; } else { node = temp; } } else { - // Node with two children → get inorder successor Node successor = findMinNode(node.right); node.key = successor.key; node.right = deleteRecursive(node.right, successor.key); } } - // If tree had only one node - if (node == null) return null; + if (node == null) { + return null; + } - // Step 2: Update height updateHeight(node); - - // Step 3: Rebalance node return balanceNode(node); } - /** Recursive search like normal BST */ private boolean searchRecursive(Node node, int key) { - if (node == null) return false; - if (key == node.key) return true; - return key < node.key ? searchRecursive(node.left, key) : searchRecursive(node.right, key); + if (node == null) { + return false; + } + if (key == node.key) { + return true; + } + if (key < node.key) { + return searchRecursive(node.left, key); + } else { + return searchRecursive(node.right, key); + } } - /** Find node with minimum key */ private Node findMinNode(Node node) { Node cur = node; - while (cur.left != null) cur = cur.left; + while (cur.left != null) { + cur = cur.left; + } return cur; } - /* ======================== ROTATIONS & BALANCING ======================== */ - - /** Right rotation (used in LL or LR imbalance) */ private Node rightRotate(Node y) { Node x = y.left; Node T2 = x.right; - // Perform rotation x.right = y; y.left = T2; - // Update heights updateHeight(y); updateHeight(x); - return x; // New root + return x; } - /** Left rotation (used in RR or RL imbalance) */ private Node leftRotate(Node x) { Node y = x.right; Node T2 = y.left; - // Perform rotation y.left = x; x.right = T2; - // Update heights updateHeight(x); updateHeight(y); - return y; // New root + return y; } - /** - * Balances a node by checking its balance factor: - * - * - If > 1 → left heavy - * - If < -1 → right heavy - * - * Depending on the case, we do: - * - LL → Right Rotate - * - RR → Left Rotate - * - LR → Left Rotate child + Right Rotate - * - RL → Right Rotate child + Left Rotate - */ private Node balanceNode(Node node) { int balance = getBalance(node); - // Case 1: Left Left (LL) - if (balance > 1 && getBalance(node.left) >= 0) return rightRotate(node); + if (balance > 1 && getBalance(node.left) >= 0) { + return rightRotate(node); + } - // Case 2: Left Right (LR) if (balance > 1 && getBalance(node.left) < 0) { node.left = leftRotate(node.left); return rightRotate(node); } - // Case 3: Right Right (RR) - if (balance < -1 && getBalance(node.right) <= 0) return leftRotate(node); + if (balance < -1 && getBalance(node.right) <= 0) { + return leftRotate(node); + } - // Case 4: Right Left (RL) if (balance < -1 && getBalance(node.right) > 0) { node.right = rightRotate(node.right); return leftRotate(node); } - return node; // Already balanced + return node; } - /* ======================== HELPER FUNCTIONS ======================== */ - - /** Returns height of a node */ private int height(Node node) { - return node == null ? 0 : node.height; + if (node == null) { + return 0; + } else { + return node.height; + } } - /** Updates height of a node based on its children */ private void updateHeight(Node node) { node.height = 1 + Math.max(height(node.left), height(node.right)); } - /** Calculates balance factor = height(left) - height(right) */ private int getBalance(Node node) { - return node == null ? 0 : height(node.left) - height(node.right); + if (node == null) { + return 0; + } else { + return height(node.left) - height(node.right); + } } - /* ======================== TRAVERSALS ======================== */ - private void printInorderRecursive(Node node) { if (node == null) { return; @@ -338,41 +291,4 @@ private void postorderToList(Node node, List out) { postorderToList(node.right, out); out.add(node.key); } - - public static void main(String[] args) { - AVL avl = new AVL(); - - int[] values = {30, 20, 40, 10, 25, 35, 50, 5, 15, 27, 45, 60}; - - // Insert all values one by one - for (int v : values) avl.insert(v); - - // Display traversals - avl.printInorder(); // should show sorted order - avl.printPreorder(); - avl.printPostorder(); - - // Display traversal lists - System.out.println("Inorder List: " + avl.inorderList()); - System.out.println("Preorder List: " + avl.preorderList()); - System.out.println("Postorder List: " + avl.postorderList()); - - // Search examples - System.out.println("Search 27: " + avl.search(27)); // true - System.out.println("Search 99: " + avl.search(99)); // false - - // Min and Max - System.out.println("Min: " + avl.findMin()); - System.out.println("Max: " + avl.findMax()); - - // Delete operations and show tree after each - avl.delete(10); - System.out.println("After deleting 10: " + avl.inorderList()); - - avl.delete(30); - System.out.println("After deleting 30: " + avl.inorderList()); - - avl.delete(40); - System.out.println("After deleting 40: " + avl.inorderList()); - } } diff --git a/src/main/java/com/thealgorithms/tree/BST.java b/src/main/java/com/thealgorithms/tree/BST.java index b42d4b49b182..14696ed21c4a 100644 --- a/src/main/java/com/thealgorithms/tree/BST.java +++ b/src/main/java/com/thealgorithms/tree/BST.java @@ -6,89 +6,65 @@ public class BST { - /** - * Node class represents a node in the BST. - * 0->0->0 - * 0=Nodes\ - * each node contains divided into 3 section - * Key-> Actual value, - * left-> store the address of left tree, - * Right-> store the address of right tree - */ private static class Node { int key; Node left, right; Node(int key) { this.key = key; - left = right = null; + this.left = null; + this.right = null; } } - // Root of the BST - // the first of Node tree - // 0-> private Node root; - /** Create an empty BST. */ public BST() { - root = null; + this.root = null; } /* =========================== * INSERT * =========================== */ - /** - * Insert a value into the BST. Duplicate values are ignored (no-op). - * - * @param value value to insert - */ public void insert(int value) { - root = insertRecursive(root, value); + this.root = insertRecursive(this.root, value); } - // Helper recursive method for insertion. private Node insertRecursive(Node node, int value) { - // If we reached a null position, create and return a new node. if (node == null) { return new Node(value); } - // If value is less, go left; if greater, go right; if equal, do nothing. if (value < node.key) { node.left = insertRecursive(node.left, value); } else if (value > node.key) { node.right = insertRecursive(node.right, value); - } // else duplicate -> ignore + } else { + // duplicate -> ignore + } - return node; // return current (possibly updated) subtree root + return node; } /* =========================== * SEARCH * =========================== */ - /** - * Search the BST for a value. - * - * @param value value to search - * @return true if value exists in the BST, false otherwise - */ public boolean search(int value) { - return searchRecursive(root, value); + return searchRecursive(this.root, value); } private boolean searchRecursive(Node node, int value) { if (node == null) { - return false; // reached leaf, not found + return false; } if (value == node.key) { - return true; // found exact match + return true; } else if (value < node.key) { - return searchRecursive(node.left, value); // search left subtree + return searchRecursive(node.left, value); } else { - return searchRecursive(node.right, value); // search right subtree + return searchRecursive(node.right, value); } } @@ -96,101 +72,71 @@ private boolean searchRecursive(Node node, int value) { * DELETE * =========================== */ - /** - * Delete a value from the BST. If the value is not present, tree remains unchanged. - * - * @param value value to delete - */ public void delete(int value) { - root = deleteRecursive(root, value); + this.root = deleteRecursive(this.root, value); } - // Helper for deletion, handles three cases: - // 1) node is a leaf -> just remove - // 2) node has one child -> replace node with child - // 3) node has two children -> replace node with successor (smallest in right subtree) private Node deleteRecursive(Node node, int value) { if (node == null) { - return null; // value not found + return null; } if (value < node.key) { - // target is in left subtree node.left = deleteRecursive(node.left, value); } else if (value > node.key) { - // target is in right subtree node.right = deleteRecursive(node.right, value); } else { - // node.key == value -> delete this node - // Case 1 & 2: node has 0 or 1 child if (node.left == null) { - // return right child (could be null) to replace node return node.right; } else if (node.right == null) { - // return left child to replace node return node.left; } - // Case 3: node has two children - // Find the inorder successor (smallest in the right subtree) Node successor = findMinNode(node.right); - // Copy successor's value to this node node.key = successor.key; - // Delete the successor node from right subtree node.right = deleteRecursive(node.right, successor.key); } return node; } - /** - * Find the minimum key in the BST. - * - * @return the smallest integer key in the tree - * @throws NoSuchElementException if the tree is empty - */ + /* =========================== + * MIN/MAX + * =========================== */ + public int findMin() { - if (root == null) { + if (this.root == null) { throw new NoSuchElementException("BST is empty"); } - return findMinNode(root).key; + return findMinNode(this.root).key; } - // Helper to find node with minimum key in a subtree (leftmost node) private Node findMinNode(Node node) { Node current = node; - // go as far left as possible while (current.left != null) { current = current.left; } return current; } - /** - * Find the maximum key in the BST. - * - * the largest integer key in the tree - * NoSuchElementException if the tree is empty - */ public int findMax() { - if (root == null) { + if (this.root == null) { throw new NoSuchElementException("BST is empty"); } - Node current = root; - // go as far right as possible + Node current = this.root; while (current.right != null) { current = current.right; } return current.key; } - /** - * Print inorder traversal (Left, Node, Right). - * InOrder -> Left, key, Right - */ + /* =========================== + * TRAVERSALS + * =========================== */ + public void printInorder() { System.out.print("Inorder: "); - printInorderRecursive(root); + printInorderRecursive(this.root); System.out.println(); } @@ -198,18 +144,14 @@ private void printInorderRecursive(Node node) { if (node == null) { return; } - printInorderRecursive(node.left); // left - System.out.print(node.key + " "); // node - printInorderRecursive(node.right); // right + printInorderRecursive(node.left); + System.out.print(node.key + " "); + printInorderRecursive(node.right); } - /** - * Print preorder traversal (Node, Left, Right). - * PreOrder -> key,Left, Right - */ public void printPreorder() { System.out.print("Preorder: "); - printPreorderRecursive(root); + printPreorderRecursive(this.root); System.out.println(); } @@ -217,18 +159,14 @@ private void printPreorderRecursive(Node node) { if (node == null) { return; } - System.out.print(node.key + " "); // node - printPreorderRecursive(node.left); // left - printPreorderRecursive(node.right); // right + System.out.print(node.key + " "); + printPreorderRecursive(node.left); + printPreorderRecursive(node.right); } - /** - * Print postorder traversal (Left, Right, Node). - *PreOrder -> key,Left, Right - */ public void printPostorder() { System.out.print("Postorder: "); - printPostorderRecursive(root); + printPostorderRecursive(this.root); System.out.println(); } @@ -236,14 +174,18 @@ private void printPostorderRecursive(Node node) { if (node == null) { return; } - printPostorderRecursive(node.left); // left - printPostorderRecursive(node.right); // right - System.out.print(node.key + " "); // node + printPostorderRecursive(node.left); + printPostorderRecursive(node.right); + System.out.print(node.key + " "); } + /* =========================== + * LIST OUTPUT + * =========================== */ + public List inorderList() { List result = new ArrayList<>(); - inorderToList(root, result); + inorderToList(this.root, result); return result; } @@ -258,12 +200,14 @@ private void inorderToList(Node node, List out) { public List preorderList() { List result = new ArrayList<>(); - preorderToList(root, result); + preorderToList(this.root, result); return result; } private void preorderToList(Node node, List out) { - if (node == null) return; + if (node == null) { + return; + } out.add(node.key); preorderToList(node.left, out); preorderToList(node.right, out); @@ -271,21 +215,26 @@ private void preorderToList(Node node, List out) { public List postorderList() { List result = new ArrayList<>(); - postorderToList(root, result); + postorderToList(this.root, result); return result; } private void postorderToList(Node node, List out) { - if (node == null) return; + if (node == null) { + return; + } postorderToList(node.left, out); postorderToList(node.right, out); out.add(node.key); } + /* =========================== + * MAIN (TEST) + * =========================== */ + public static void main(String[] args) { BST bst = new BST(); - // Insert values int[] values = {50, 30, 70, 20, 40, 60, 80}; for (int v : values) { bst.insert(v); @@ -299,11 +248,11 @@ public static void main(String[] args) { System.out.println("Preorder List: " + bst.preorderList()); System.out.println("Postorder List: " + bst.postorderList()); - System.out.println("Search 40: " + bst.search(40)); // true - System.out.println("Search 99: " + bst.search(99)); // false + System.out.println("Search 40: " + bst.search(40)); + System.out.println("Search 99: " + bst.search(99)); - System.out.println("Min: " + bst.findMin()); // 20 - System.out.println("Max: " + bst.findMax()); // 80 + System.out.println("Min: " + bst.findMin()); + System.out.println("Max: " + bst.findMax()); bst.delete(20); System.out.println("After deleting 20 (leaf): " + bst.inorderList()); diff --git a/src/test/java/com/thealgorithms/tree/AVLTest.java b/src/test/java/com/thealgorithms/tree/AVLTest.java index d135e40fbf27..355bc941b4c8 100644 --- a/src/test/java/com/thealgorithms/tree/AVLTest.java +++ b/src/test/java/com/thealgorithms/tree/AVLTest.java @@ -14,80 +14,89 @@ private static class Node { Node(int key) { this.key = key; this.height = 1; // new node is initially added at leaf - this.left = this.right = null; + this.left = null; + this.right = null; } } private Node root; public AVLTest() { - root = null; + this.root = null; } public void insert(int key) { - root = insertRecursive(root, key); + this.root = insertRecursive(this.root, key); } public void delete(int key) { - root = deleteRecursive(root, key); + this.root = deleteRecursive(this.root, key); } public boolean search(int key) { - return searchRecursive(root, key); + return searchRecursive(this.root, key); } public int findMin() { - if (root == null) throw new NoSuchElementException("AVL is empty"); - return findMinNode(root).key; + if (this.root == null) { + throw new NoSuchElementException("AVL is empty"); + } + return findMinNode(this.root).key; } public int findMax() { - if (root == null) throw new NoSuchElementException("AVL is empty"); - Node cur = root; - while (cur.right != null) cur = cur.right; + if (this.root == null) { + throw new NoSuchElementException("AVL is empty"); + } + Node cur = this.root; + while (cur.right != null) { + cur = cur.right; + } return cur.key; } public void printInorder() { System.out.print("Inorder: "); - printInorderRecursive(root); + printInorderRecursive(this.root); System.out.println(); } public void printPreorder() { System.out.print("Preorder: "); - printPreorderRecursive(root); + printPreorderRecursive(this.root); System.out.println(); } public void printPostorder() { System.out.print("Postorder: "); - printPostorderRecursive(root); + printPostorderRecursive(this.root); System.out.println(); } public List inorderList() { List res = new ArrayList<>(); - inorderToList(root, res); + inorderToList(this.root, res); return res; } public List preorderList() { List res = new ArrayList<>(); - preorderToList(root, res); + preorderToList(this.root, res); return res; } public List postorderList() { List res = new ArrayList<>(); - postorderToList(root, res); + postorderToList(this.root, res); return res; } /* Recursive helpers */ private Node insertRecursive(Node node, int key) { - if (node == null) return new Node(key); + if (node == null) { + return new Node(key); + } if (key < node.key) { node.left = insertRecursive(node.left, key); @@ -125,21 +134,33 @@ private Node deleteRecursive(Node node, int key) { } } - if (node == null) return null; + if (node == null) { + return null; + } updateHeight(node); return balanceNode(node); } private boolean searchRecursive(Node node, int key) { - if (node == null) return false; - if (key == node.key) return true; - return key < node.key ? searchRecursive(node.left, key) : searchRecursive(node.right, key); + if (node == null) { + return false; + } + if (key == node.key) { + return true; + } + if (key < node.key) { + return searchRecursive(node.left, key); + } else { + return searchRecursive(node.right, key); + } } private Node findMinNode(Node node) { Node cur = node; - while (cur.left != null) cur = cur.left; + while (cur.left != null) { + cur = cur.left; + } return cur; } @@ -179,7 +200,7 @@ private Node balanceNode(Node node) { } if (balance > 1 && getBalance(node.left) < 0) { - node.left = leftRotate(node.left); // LR: left then right + node.left = leftRotate(node.left); // LR return rightRotate(node); } @@ -188,7 +209,7 @@ private Node balanceNode(Node node) { } if (balance < -1 && getBalance(node.right) > 0) { - node.right = rightRotate(node.right); // RL: right then left + node.right = rightRotate(node.right); // RL return leftRotate(node); } @@ -196,7 +217,10 @@ private Node balanceNode(Node node) { } private int height(Node node) { - return node == null ? 0 : node.height; + if (node == null) { + return 0; + } + return node.height; } private void updateHeight(Node node) { @@ -204,50 +228,97 @@ private void updateHeight(Node node) { } private int getBalance(Node node) { - return node == null ? 0 : height(node.left) - height(node.right); + if (node == null) { + return 0; + } + return height(node.left) - height(node.right); } /* ============ Traversal helpers ============ */ private void printInorderRecursive(Node node) { - if (node == null) return; + if (node == null) { + return; + } printInorderRecursive(node.left); System.out.print(node.key + " "); printInorderRecursive(node.right); } private void printPreorderRecursive(Node node) { - if (node == null) return; + if (node == null) { + return; + } System.out.print(node.key + " "); printPreorderRecursive(node.left); printPreorderRecursive(node.right); } private void printPostorderRecursive(Node node) { - if (node == null) return; + if (node == null) { + return; + } printPostorderRecursive(node.left); printPostorderRecursive(node.right); System.out.print(node.key + " "); } private void inorderToList(Node node, List out) { - if (node == null) return; + if (node == null) { + return; + } inorderToList(node.left, out); out.add(node.key); inorderToList(node.right, out); } private void preorderToList(Node node, List out) { - if (node == null) return; + if (node == null) { + return; + } out.add(node.key); preorderToList(node.left, out); preorderToList(node.right, out); } private void postorderToList(Node node, List out) { - if (node == null) return; + if (node == null) { + return; + } postorderToList(node.left, out); postorderToList(node.right, out); out.add(node.key); } + public static void main(String[] args) { + AVL avl = new AVL(); + + int[] values = {30, 20, 40, 10, 25, 35, 50, 5, 15, 27, 45, 60}; + + for (int v : values) { + avl.insert(v); + } + + avl.printInorder(); + avl.printPreorder(); + avl.printPostorder(); + + System.out.println("Inorder List: " + avl.inorderList()); + System.out.println("Preorder List: " + avl.preorderList()); + System.out.println("Postorder List: " + avl.postorderList()); + + System.out.println("Search 27: " + avl.search(27)); + System.out.println("Search 99: " + avl.search(99)); + + System.out.println("Min: " + avl.findMin()); + System.out.println("Max: " + avl.findMax()); + + avl.delete(10); + System.out.println("After deleting 10: " + avl.inorderList()); + + avl.delete(30); + System.out.println("After deleting 30: " + avl.inorderList()); + + avl.delete(40); + System.out.println("After deleting 40: " + avl.inorderList()); + } } diff --git a/src/test/java/com/thealgorithms/tree/BSTTest.java b/src/test/java/com/thealgorithms/tree/BSTTest.java index c5af9cd16c74..8605213213bb 100644 --- a/src/test/java/com/thealgorithms/tree/BSTTest.java +++ b/src/test/java/com/thealgorithms/tree/BSTTest.java @@ -6,15 +6,6 @@ public class BSTTest { - /** - * Node class represents a node in the BST. - * 0->0->0 - * 0=Nodes\ - * each node contains divided into 3 section - * Key-> Actual value, - * left-> store the address of left tree, - * Right-> store the address of right tree - */ private static class Node { int key; Node left, right; @@ -25,128 +16,77 @@ private static class Node { } } - // Root of the BST - // the first of Node tree - // 0-> private Node root; - /** Create an empty BST. */ public BSTTest() { root = null; } - /* =========================== - * INSERT - * =========================== */ - - /** - * Insert a value into the BST. Duplicate values are ignored (no-op). - * - * @param value value to insert - */ public void insert(int value) { root = insertRecursive(root, value); } - // Helper recursive method for insertion. private Node insertRecursive(Node node, int value) { - // If we reached a null position, create and return a new node. if (node == null) { return new Node(value); } - // If value is less, go left; if greater, go right; if equal, do nothing. if (value < node.key) { node.left = insertRecursive(node.left, value); } else if (value > node.key) { node.right = insertRecursive(node.right, value); - } // else duplicate -> ignore + } else { + // else duplicate -> ignore + } - return node; // return current (possibly updated) subtree root + return node; } - /* =========================== - * SEARCH - * =========================== */ - - /** - * Search the BST for a value. - * - */ public boolean search(int value) { return searchRecursive(root, value); } private boolean searchRecursive(Node node, int value) { if (node == null) { - return false; // reached leaf, not found + return false; } if (value == node.key) { - return true; // found exact match + return true; } else if (value < node.key) { - return searchRecursive(node.left, value); // search left subtree + return searchRecursive(node.left, value); } else { - return searchRecursive(node.right, value); // search right subtree + return searchRecursive(node.right, value); } } - /* =========================== - * DELETE - * =========================== */ - - /** - * Delete a value from the BST. If the value is not present, tree remains unchanged. - * - * @param value value to delete - */ public void delete(int value) { root = deleteRecursive(root, value); } - // Helper for deletion, handles three cases: - // 1) node is a leaf -> just remove - // 2) node has one child -> replace node with child - // 3) node has two children -> replace node with successor (smallest in right subtree) private Node deleteRecursive(Node node, int value) { if (node == null) { - return null; // value not found + return null; } if (value < node.key) { - // target is in left subtree node.left = deleteRecursive(node.left, value); } else if (value > node.key) { - // target is in right subtree node.right = deleteRecursive(node.right, value); } else { - // node.key == value -> delete this node - // Case 1 & 2: node has 0 or 1 child if (node.left == null) { - // return right child (could be null) to replace node return node.right; } else if (node.right == null) { - // return left child to replace node return node.left; + } else { + Node successor = findMinNode(node.right); + node.key = successor.key; + node.right = deleteRecursive(node.right, successor.key); } - - // Case 3: node has two children - // Find the inorder successor (smallest in the right subtree) - Node successor = findMinNode(node.right); - // Copy successor's value to this node - node.key = successor.key; - // Delete the successor node from right subtree - node.right = deleteRecursive(node.right, successor.key); } return node; } - /** - * Find the minimum key in the BST. - * - * @return the smallest integer key in the tree - * @throws NoSuchElementException if the tree is empty - */ public int findMin() { if (root == null) { throw new NoSuchElementException("BST is empty"); @@ -154,38 +94,25 @@ public int findMin() { return findMinNode(root).key; } - // Helper to find node with minimum key in a subtree (leftmost node) private Node findMinNode(Node node) { Node current = node; - // go as far left as possible while (current.left != null) { current = current.left; } return current; } - /** - * Find the maximum key in the BST. - * - * the largest integer key in the tree - * NoSuchElementException if the tree is empty - */ public int findMax() { if (root == null) { throw new NoSuchElementException("BST is empty"); } Node current = root; - // go as far right as possible while (current.right != null) { current = current.right; } return current.key; } - /** - * Print inorder traversal (Left, Node, Right). - * InOrder -> Left, key, Right - */ public void printInorder() { System.out.print("Inorder: "); printInorderRecursive(root); @@ -196,15 +123,11 @@ private void printInorderRecursive(Node node) { if (node == null) { return; } - printInorderRecursive(node.left); // left - System.out.print(node.key + " "); // node - printInorderRecursive(node.right); // right + printInorderRecursive(node.left); + System.out.print(node.key + " "); + printInorderRecursive(node.right); } - /** - * Print preorder traversal (Node, Left, Right). - * PreOrder -> key,Left, Right - */ public void printPreorder() { System.out.print("Preorder: "); printPreorderRecursive(root); @@ -215,15 +138,11 @@ private void printPreorderRecursive(Node node) { if (node == null) { return; } - System.out.print(node.key + " "); // node - printPreorderRecursive(node.left); // left - printPreorderRecursive(node.right); // right + System.out.print(node.key + " "); + printPreorderRecursive(node.left); + printPreorderRecursive(node.right); } - /** - * Print postorder traversal (Left, Right, Node). - *PreOrder -> key,Left, Right - */ public void printPostorder() { System.out.print("Postorder: "); printPostorderRecursive(root); @@ -234,9 +153,9 @@ private void printPostorderRecursive(Node node) { if (node == null) { return; } - printPostorderRecursive(node.left); // left - printPostorderRecursive(node.right); // right - System.out.print(node.key + " "); // node + printPostorderRecursive(node.left); + printPostorderRecursive(node.right); + System.out.print(node.key + " "); } public List inorderList() { @@ -283,6 +202,7 @@ private void postorderToList(Node node, List out) { postorderToList(node.right, out); out.add(node.key); } + public static void main(String[] args) { BSTTest bst = new BSTTest(); From 627506478fb04427de2e57a27bf395953754b17d Mon Sep 17 00:00:00 2001 From: amarmaurya-com Date: Thu, 30 Oct 2025 23:50:59 +0530 Subject: [PATCH 7/8] Added AVL tree implementation with detailed comments --- src/main/java/com/thealgorithms/tree/AVL.java | 11 ++++++----- src/main/java/com/thealgorithms/tree/BST.java | 3 ++- src/test/java/com/thealgorithms/tree/AVLTest.java | 13 +++++++------ src/test/java/com/thealgorithms/tree/BSTTest.java | 9 +++++---- 4 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/thealgorithms/tree/AVL.java b/src/main/java/com/thealgorithms/tree/AVL.java index 60463c7f7c12..df5641c7801a 100644 --- a/src/main/java/com/thealgorithms/tree/AVL.java +++ b/src/main/java/com/thealgorithms/tree/AVL.java @@ -14,8 +14,9 @@ private static class Node { Node(int key) { this.key = key; - left = right = null; this.height = 1; + this.left = null; + this.right = null; } } @@ -170,10 +171,10 @@ private Node findMinNode(Node node) { private Node rightRotate(Node y) { Node x = y.left; - Node T2 = x.right; + Node t2 = x.right; x.right = y; - y.left = T2; + y.left = t2; updateHeight(y); updateHeight(x); @@ -183,10 +184,10 @@ private Node rightRotate(Node y) { private Node leftRotate(Node x) { Node y = x.right; - Node T2 = y.left; + Node t2 = y.left; y.left = x; - x.right = T2; + x.right = t2; updateHeight(x); updateHeight(y); diff --git a/src/main/java/com/thealgorithms/tree/BST.java b/src/main/java/com/thealgorithms/tree/BST.java index 14696ed21c4a..43f1c55f5f19 100644 --- a/src/main/java/com/thealgorithms/tree/BST.java +++ b/src/main/java/com/thealgorithms/tree/BST.java @@ -8,7 +8,8 @@ public class BST { private static class Node { int key; - Node left, right; + Node left; + Node right; Node(int key) { this.key = key; diff --git a/src/test/java/com/thealgorithms/tree/AVLTest.java b/src/test/java/com/thealgorithms/tree/AVLTest.java index 355bc941b4c8..a24a4e031b89 100644 --- a/src/test/java/com/thealgorithms/tree/AVLTest.java +++ b/src/test/java/com/thealgorithms/tree/AVLTest.java @@ -9,11 +9,12 @@ public class AVLTest { private static class Node { int key; int height; - Node left, right; + Node left; + Node right; Node(int key) { this.key = key; - this.height = 1; // new node is initially added at leaf + this.height = 1; this.left = null; this.right = null; } @@ -168,10 +169,10 @@ private Node findMinNode(Node node) { private Node rightRotate(Node y) { Node x = y.left; - Node T2 = x.right; + Node t2 = x.right; x.right = y; - y.left = T2; + y.left = t2; updateHeight(y); updateHeight(x); @@ -181,10 +182,10 @@ private Node rightRotate(Node y) { private Node leftRotate(Node x) { Node y = x.right; - Node T2 = y.left; + Node t2 = y.left; y.left = x; - x.right = T2; + x.right = t2; updateHeight(x); updateHeight(y); diff --git a/src/test/java/com/thealgorithms/tree/BSTTest.java b/src/test/java/com/thealgorithms/tree/BSTTest.java index 8605213213bb..d58e05c6fc14 100644 --- a/src/test/java/com/thealgorithms/tree/BSTTest.java +++ b/src/test/java/com/thealgorithms/tree/BSTTest.java @@ -8,13 +8,14 @@ public class BSTTest { private static class Node { int key; - Node left, right; + Node left; + Node right; Node(int key) { this.key = key; - left = right = null; - } - } + this.left = null; + this.right = null; + } } private Node root; From f137558dc80f321ac2fa62728dd8ce5be3e01e64 Mon Sep 17 00:00:00 2001 From: amarmaurya-com Date: Thu, 30 Oct 2025 23:56:37 +0530 Subject: [PATCH 8/8] Added AVL tree implementation with detailed comments --- src/test/java/com/thealgorithms/tree/BSTTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/thealgorithms/tree/BSTTest.java b/src/test/java/com/thealgorithms/tree/BSTTest.java index d58e05c6fc14..f1570e72c91e 100644 --- a/src/test/java/com/thealgorithms/tree/BSTTest.java +++ b/src/test/java/com/thealgorithms/tree/BSTTest.java @@ -15,7 +15,8 @@ private static class Node { this.key = key; this.left = null; this.right = null; - } } + } + } private Node root;