Skip to content

Commit 49d0a66

Browse files
committed
feat: Add Binary Search Tree (BST) and AVL Tree implementations
1 parent fa8ea8e commit 49d0a66

6 files changed

Lines changed: 634 additions & 0 deletions

File tree

src/main/java/trees/AVLTree.java

Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
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

Comments
 (0)