44import java .util .List ;
55import java .util .NoSuchElementException ;
66
7- /**
8- * AVL (Adelson-Velsky and Landis) Tree is a self-balancing Binary Search Tree.
9- * Operations supported:
10- * - insert, delete, search
11- * - inorder, preorder, postorder traversal
12- * - findMin(), findMax()
13- *
14- * Properties:
15- * - For every node: |height(left) - height(right)| <= 1
16- * - Maintains O(log n) time complexity for insert/delete/search
17- */
187public class AVL {
198
20- /**
21- * Inner class to represent a node in AVL Tree
22- */
239 private static class Node {
2410 int key ;
2511 int height ;
@@ -28,263 +14,230 @@ private static class Node {
2814
2915 Node (int key ) {
3016 this .key = key ;
31- this .height = 1 ; // New node starts as a leaf node with height = 1
17+ left = right = null ;
18+ this .height = 1 ;
3219 }
3320 }
3421
35- // Root node of the AVL Tree
3622 private Node root ;
3723
38- // Constructor
3924 public AVL () {
4025 root = null ;
4126 }
4227
43- /* ======================== PUBLIC METHODS ======================== */
44-
45- /** Insert a key into the AVL Tree */
4628 public void insert (int key ) {
4729 root = insertRecursive (root , key );
4830 }
4931
50- /** Delete a key from the AVL Tree */
5132 public void delete (int key ) {
5233 root = deleteRecursive (root , key );
5334 }
5435
55- /** Search a key in the AVL Tree */
5636 public boolean search (int key ) {
5737 return searchRecursive (root , key );
5838 }
5939
60- /** Return the smallest key in the AVL Tree */
6140 public int findMin () {
62- if (root == null ) throw new NoSuchElementException ("AVL Tree is empty" );
41+ if (root == null ) {
42+ throw new NoSuchElementException ("AVL Tree is empty" );
43+ }
6344 return findMinNode (root ).key ;
6445 }
6546
66- /** Return the largest key in the AVL Tree */
6747 public int findMax () {
68- if (root == null ) throw new NoSuchElementException ("AVL Tree is empty" );
48+ if (root == null ) {
49+ throw new NoSuchElementException ("AVL Tree is empty" );
50+ }
6951 Node cur = root ;
70- while (cur .right != null ) cur = cur .right ;
52+ while (cur .right != null ) {
53+ cur = cur .right ;
54+ }
7155 return cur .key ;
7256 }
7357
74- /** Print nodes in Inorder (sorted order) */
7558 public void printInorder () {
7659 System .out .print ("Inorder: " );
7760 printInorderRecursive (root );
7861 System .out .println ();
7962 }
8063
81- /** Print nodes in Preorder (Root → Left → Right) */
8264 public void printPreorder () {
8365 System .out .print ("Preorder: " );
8466 printPreorderRecursive (root );
8567 System .out .println ();
8668 }
8769
88- /** Print nodes in Postorder (Left → Right → Root) */
8970 public void printPostorder () {
9071 System .out .print ("Postorder: " );
9172 printPostorderRecursive (root );
9273 System .out .println ();
9374 }
9475
95- /** Return Inorder list (useful for testing) */
9676 public List <Integer > inorderList () {
9777 List <Integer > res = new ArrayList <>();
9878 inorderToList (root , res );
9979 return res ;
10080 }
10181
102- /** Return Preorder list (useful for testing) */
10382 public List <Integer > preorderList () {
10483 List <Integer > res = new ArrayList <>();
10584 preorderToList (root , res );
10685 return res ;
10786 }
10887
109- /** Return Postorder list (useful for testing) */
11088 public List <Integer > postorderList () {
11189 List <Integer > res = new ArrayList <>();
11290 postorderToList (root , res );
11391 return res ;
11492 }
11593
116- /**
117- * Recursive insert:
118- * 1. Insert key like a normal BST
119- * 2. Update height of current node
120- * 3. Balance the node if it became unbalanced
121- */
12294 private Node insertRecursive (Node node , int key ) {
123- // Step 1: Perform standard BST insert
12495 if (node == null ) {
12596 return new Node (key );
12697 }
12798
128- if (key < node .key )
99+ if (key < node .key ) {
129100 node .left = insertRecursive (node .left , key );
130- else if (key > node .key )
101+ } else if (key > node .key ) {
131102 node .right = insertRecursive (node .right , key );
132- else
133- return node ; // Duplicates not allowed
103+ } else {
104+ return node ;
105+ }
134106
135- // Step 2: Update height of ancestor node
136107 updateHeight (node );
137-
138- // Step 3: Balance the node and return new root
139108 return balanceNode (node );
140109 }
141110
142- /**
143- * Recursive delete:
144- * 1. Perform normal BST delete
145- * 2. Update height of current node
146- * 3. Balance it if necessary
147- */
148111 private Node deleteRecursive (Node node , int key ) {
149- if (node == null ) return null ;
112+ if (node == null ) {
113+ return null ;
114+ }
150115
151- // Step 1: Perform BST delete
152- if (key < node .key )
116+ if (key < node .key ) {
153117 node .left = deleteRecursive (node .left , key );
154- else if (key > node .key )
118+ } else if (key > node .key ) {
155119 node .right = deleteRecursive (node .right , key );
156- else {
157- // Node found
120+ } else {
158121 if (node .left == null || node .right == null ) {
159- Node temp = (node .left != null ) ? node .left : node .right ;
122+ Node temp = null ;
123+ if (node .left != null ) {
124+ temp = node .left ;
125+ } else {
126+ temp = node .right ;
127+ }
160128
161- // No child case
162129 if (temp == null ) {
163130 node = null ;
164131 } else {
165132 node = temp ;
166133 }
167134 } else {
168- // Node with two children → get inorder successor
169135 Node successor = findMinNode (node .right );
170136 node .key = successor .key ;
171137 node .right = deleteRecursive (node .right , successor .key );
172138 }
173139 }
174140
175- // If tree had only one node
176- if (node == null ) return null ;
141+ if (node == null ) {
142+ return null ;
143+ }
177144
178- // Step 2: Update height
179145 updateHeight (node );
180-
181- // Step 3: Rebalance node
182146 return balanceNode (node );
183147 }
184148
185- /** Recursive search like normal BST */
186149 private boolean searchRecursive (Node node , int key ) {
187- if (node == null ) return false ;
188- if (key == node .key ) return true ;
189- return key < node .key ? searchRecursive (node .left , key ) : searchRecursive (node .right , key );
150+ if (node == null ) {
151+ return false ;
152+ }
153+ if (key == node .key ) {
154+ return true ;
155+ }
156+ if (key < node .key ) {
157+ return searchRecursive (node .left , key );
158+ } else {
159+ return searchRecursive (node .right , key );
160+ }
190161 }
191162
192- /** Find node with minimum key */
193163 private Node findMinNode (Node node ) {
194164 Node cur = node ;
195- while (cur .left != null ) cur = cur .left ;
165+ while (cur .left != null ) {
166+ cur = cur .left ;
167+ }
196168 return cur ;
197169 }
198170
199- /* ======================== ROTATIONS & BALANCING ======================== */
200-
201- /** Right rotation (used in LL or LR imbalance) */
202171 private Node rightRotate (Node y ) {
203172 Node x = y .left ;
204173 Node T2 = x .right ;
205174
206- // Perform rotation
207175 x .right = y ;
208176 y .left = T2 ;
209177
210- // Update heights
211178 updateHeight (y );
212179 updateHeight (x );
213180
214- return x ; // New root
181+ return x ;
215182 }
216183
217- /** Left rotation (used in RR or RL imbalance) */
218184 private Node leftRotate (Node x ) {
219185 Node y = x .right ;
220186 Node T2 = y .left ;
221187
222- // Perform rotation
223188 y .left = x ;
224189 x .right = T2 ;
225190
226- // Update heights
227191 updateHeight (x );
228192 updateHeight (y );
229193
230- return y ; // New root
194+ return y ;
231195 }
232196
233- /**
234- * Balances a node by checking its balance factor:
235- *
236- * - If > 1 → left heavy
237- * - If < -1 → right heavy
238- *
239- * Depending on the case, we do:
240- * - LL → Right Rotate
241- * - RR → Left Rotate
242- * - LR → Left Rotate child + Right Rotate
243- * - RL → Right Rotate child + Left Rotate
244- */
245197 private Node balanceNode (Node node ) {
246198 int balance = getBalance (node );
247199
248- // Case 1: Left Left (LL)
249- if (balance > 1 && getBalance (node .left ) >= 0 ) return rightRotate (node );
200+ if (balance > 1 && getBalance (node .left ) >= 0 ) {
201+ return rightRotate (node );
202+ }
250203
251- // Case 2: Left Right (LR)
252204 if (balance > 1 && getBalance (node .left ) < 0 ) {
253205 node .left = leftRotate (node .left );
254206 return rightRotate (node );
255207 }
256208
257- // Case 3: Right Right (RR)
258- if (balance < -1 && getBalance (node .right ) <= 0 ) return leftRotate (node );
209+ if (balance < -1 && getBalance (node .right ) <= 0 ) {
210+ return leftRotate (node );
211+ }
259212
260- // Case 4: Right Left (RL)
261213 if (balance < -1 && getBalance (node .right ) > 0 ) {
262214 node .right = rightRotate (node .right );
263215 return leftRotate (node );
264216 }
265217
266- return node ; // Already balanced
218+ return node ;
267219 }
268220
269- /* ======================== HELPER FUNCTIONS ======================== */
270-
271- /** Returns height of a node */
272221 private int height (Node node ) {
273- return node == null ? 0 : node .height ;
222+ if (node == null ) {
223+ return 0 ;
224+ } else {
225+ return node .height ;
226+ }
274227 }
275228
276- /** Updates height of a node based on its children */
277229 private void updateHeight (Node node ) {
278230 node .height = 1 + Math .max (height (node .left ), height (node .right ));
279231 }
280232
281- /** Calculates balance factor = height(left) - height(right) */
282233 private int getBalance (Node node ) {
283- return node == null ? 0 : height (node .left ) - height (node .right );
234+ if (node == null ) {
235+ return 0 ;
236+ } else {
237+ return height (node .left ) - height (node .right );
238+ }
284239 }
285240
286- /* ======================== TRAVERSALS ======================== */
287-
288241 private void printInorderRecursive (Node node ) {
289242 if (node == null ) {
290243 return ;
@@ -338,41 +291,4 @@ private void postorderToList(Node node, List<Integer> out) {
338291 postorderToList (node .right , out );
339292 out .add (node .key );
340293 }
341-
342- public static void main (String [] args ) {
343- AVL avl = new AVL ();
344-
345- int [] values = {30 , 20 , 40 , 10 , 25 , 35 , 50 , 5 , 15 , 27 , 45 , 60 };
346-
347- // Insert all values one by one
348- for (int v : values ) avl .insert (v );
349-
350- // Display traversals
351- avl .printInorder (); // should show sorted order
352- avl .printPreorder ();
353- avl .printPostorder ();
354-
355- // Display traversal lists
356- System .out .println ("Inorder List: " + avl .inorderList ());
357- System .out .println ("Preorder List: " + avl .preorderList ());
358- System .out .println ("Postorder List: " + avl .postorderList ());
359-
360- // Search examples
361- System .out .println ("Search 27: " + avl .search (27 )); // true
362- System .out .println ("Search 99: " + avl .search (99 )); // false
363-
364- // Min and Max
365- System .out .println ("Min: " + avl .findMin ());
366- System .out .println ("Max: " + avl .findMax ());
367-
368- // Delete operations and show tree after each
369- avl .delete (10 );
370- System .out .println ("After deleting 10: " + avl .inorderList ());
371-
372- avl .delete (30 );
373- System .out .println ("After deleting 30: " + avl .inorderList ());
374-
375- avl .delete (40 );
376- System .out .println ("After deleting 40: " + avl .inorderList ());
377- }
378294}
0 commit comments