1+ package trees ;
2+
3+ /**
4+ * AVL Tree Implementation (Self-Balancing Binary Search Tree)
5+ * Maintains balance factor to ensure O(log n) operations
6+ * Supports: insert, delete, search, rotations (LL, RR, LR, RL)
7+ */
8+ public class AVLTree {
9+ private TreeNode root ;
10+
11+ public AVLTree () {
12+ this .root = null ;
13+ }
14+
15+ // ============= HEIGHT MANAGEMENT =============
16+ private int getHeight (TreeNode node ) {
17+ return node == null ? 0 : node .height ;
18+ }
19+
20+ private int getBalance (TreeNode node ) {
21+ return node == null ? 0 : getHeight (node .left ) - getHeight (node .right );
22+ }
23+
24+ private void updateHeight (TreeNode node ) {
25+ if (node != null ) {
26+ node .height = 1 + Math .max (getHeight (node .left ), getHeight (node .right ));
27+ }
28+ }
29+
30+ // ============= ROTATION OPERATIONS =============
31+ // Right Rotation (LL case)
32+ private TreeNode rotateRight (TreeNode y ) {
33+ TreeNode x = y .left ;
34+ TreeNode T2 = x .right ;
35+
36+ x .right = y ;
37+ y .left = T2 ;
38+
39+ updateHeight (y );
40+ updateHeight (x );
41+
42+ return x ;
43+ }
44+
45+ // Left Rotation (RR case)
46+ private TreeNode rotateLeft (TreeNode x ) {
47+ TreeNode y = x .right ;
48+ TreeNode T2 = y .left ;
49+
50+ y .left = x ;
51+ x .right = T2 ;
52+
53+ updateHeight (x );
54+ updateHeight (y );
55+
56+ return y ;
57+ }
58+
59+ // ============= INSERT OPERATION =============
60+ public void insert (int value ) {
61+ root = insertRecursive (root , value );
62+ }
63+
64+ private TreeNode insertRecursive (TreeNode node , int value ) {
65+ if (node == null ) {
66+ return new TreeNode (value );
67+ }
68+
69+ if (value < node .value ) {
70+ node .left = insertRecursive (node .left , value );
71+ } else if (value > node .value ) {
72+ node .right = insertRecursive (node .right , value );
73+ } else {
74+ return node ; // Duplicate ignored
75+ }
76+
77+ updateHeight (node );
78+ return balance (node );
79+ }
80+
81+ // ============= BALANCE OPERATION =============
82+ private TreeNode balance (TreeNode node ) {
83+ int balanceFactor = getBalance (node );
84+
85+ // Left Heavy Cases
86+ if (balanceFactor > 1 ) {
87+ if (getBalance (node .left ) < 0 ) {
88+ // LR case: Left-Right
89+ node .left = rotateLeft (node .left );
90+ }
91+ // LL case: Left-Left
92+ return rotateRight (node );
93+ }
94+
95+ // Right Heavy Cases
96+ if (balanceFactor < -1 ) {
97+ if (getBalance (node .right ) > 0 ) {
98+ // RL case: Right-Left
99+ node .right = rotateRight (node .right );
100+ }
101+ // RR case: Right-Right
102+ return rotateLeft (node );
103+ }
104+
105+ return node ;
106+ }
107+
108+ // ============= DELETE OPERATION =============
109+ public void delete (int value ) {
110+ root = deleteRecursive (root , value );
111+ }
112+
113+ private TreeNode deleteRecursive (TreeNode node , int value ) {
114+ if (node == null ) {
115+ return null ;
116+ }
117+
118+ if (value < node .value ) {
119+ node .left = deleteRecursive (node .left , value );
120+ } else if (value > node .value ) {
121+ node .right = deleteRecursive (node .right , value );
122+ } else {
123+ // Node to delete found
124+ if (node .left == null && node .right == null ) {
125+ return null ;
126+ }
127+ if (node .left == null ) {
128+ return node .right ;
129+ }
130+ if (node .right == null ) {
131+ return node .left ;
132+ }
133+
134+ TreeNode minRight = findMinNode (node .right );
135+ node .value = minRight .value ;
136+ node .right = deleteRecursive (node .right , minRight .value );
137+ }
138+
139+ updateHeight (node );
140+ return balance (node );
141+ }
142+
143+ // ============= SEARCH OPERATION =============
144+ public boolean search (int value ) {
145+ return searchRecursive (root , value );
146+ }
147+
148+ private boolean searchRecursive (TreeNode node , int value ) {
149+ if (node == null ) {
150+ return false ;
151+ }
152+
153+ if (value == node .value ) {
154+ return true ;
155+ } else if (value < node .value ) {
156+ return searchRecursive (node .left , value );
157+ } else {
158+ return searchRecursive (node .right , value );
159+ }
160+ }
161+
162+ // ============= UTILITY METHODS =============
163+ public int findMin () {
164+ if (root == null ) {
165+ throw new IllegalStateException ("Tree is empty" );
166+ }
167+ return findMinNode (root ).value ;
168+ }
169+
170+ private TreeNode findMinNode (TreeNode node ) {
171+ while (node .left != null ) {
172+ node = node .left ;
173+ }
174+ return node ;
175+ }
176+
177+ public int findMax () {
178+ if (root == null ) {
179+ throw new IllegalStateException ("Tree is empty" );
180+ }
181+ return findMaxNode (root ).value ;
182+ }
183+
184+ private TreeNode findMaxNode (TreeNode node ) {
185+ while (node .right != null ) {
186+ node = node .right ;
187+ }
188+ return node ;
189+ }
190+
191+ // ============= TREE TRAVERSALS =============
192+ public void inorder () {
193+ System .out .print ("Inorder: " );
194+ inorderRecursive (root );
195+ System .out .println ();
196+ }
197+
198+ private void inorderRecursive (TreeNode node ) {
199+ if (node != null ) {
200+ inorderRecursive (node .left );
201+ System .out .print (node .value + " " );
202+ inorderRecursive (node .right );
203+ }
204+ }
205+
206+ public void preorder () {
207+ System .out .print ("Preorder: " );
208+ preorderRecursive (root );
209+ System .out .println ();
210+ }
211+
212+ private void preorderRecursive (TreeNode node ) {
213+ if (node != null ) {
214+ System .out .print (node .value + " " );
215+ preorderRecursive (node .left );
216+ preorderRecursive (node .right );
217+ }
218+ }
219+
220+ public void postorder () {
221+ System .out .print ("Postorder: " );
222+ postorderRecursive (root );
223+ System .out .println ();
224+ }
225+
226+ private void postorderRecursive (TreeNode node ) {
227+ if (node != null ) {
228+ postorderRecursive (node .left );
229+ postorderRecursive (node .right );
230+ System .out .print (node .value + " " );
231+ }
232+ }
233+
234+ // ============= HELPER METHODS =============
235+ public int getHeight () {
236+ return getHeight (root );
237+ }
238+
239+ public boolean isEmpty () {
240+ return root == null ;
241+ }
242+
243+ public void clear () {
244+ root = null ;
245+ }
246+ }
0 commit comments