Skip to content

Commit b31bc86

Browse files
authored
Enhance docs, add tests in AVLTree (TheAlgorithms#6058)
1 parent e94be71 commit b31bc86

File tree

3 files changed

+184
-62
lines changed

3 files changed

+184
-62
lines changed

DIRECTORY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -912,6 +912,7 @@
912912
* [StackArrayTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/stacks/StackArrayTest.java)
913913
* [StackOfLinkedListTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/stacks/StackOfLinkedListTest.java)
914914
* trees
915+
* [AVLTreeTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/trees/AVLTreeTest.java)
915916
* [BinaryTreeTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/trees/BinaryTreeTest.java)
916917
* [BoundaryTraversalTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/trees/BoundaryTraversalTest.java)
917918
* [BSTFromSortedArrayTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/trees/BSTFromSortedArrayTest.java)

src/main/java/com/thealgorithms/datastructures/trees/AVLTree.java

Lines changed: 82 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11
package com.thealgorithms.datastructures.trees;
22

3+
import java.util.ArrayList;
4+
import java.util.List;
5+
6+
/**
7+
* Represents an AVL Tree, a self-balancing binary search tree.
8+
* In an AVL tree, the heights of the two child subtrees of any node
9+
* differ by at most one. If they differ by more than one at any time,
10+
* rebalancing is performed to restore this property.
11+
*/
312
public class AVLTree {
413

514
private Node root;
615

7-
private class Node {
8-
16+
private static class Node {
917
private int key;
1018
private int balance;
1119
private int height;
@@ -17,8 +25,18 @@ private class Node {
1725
key = k;
1826
parent = p;
1927
}
28+
29+
public Integer getBalance() {
30+
return balance;
31+
}
2032
}
2133

34+
/**
35+
* Inserts a new key into the AVL tree.
36+
*
37+
* @param key the key to be inserted
38+
* @return {@code true} if the key was inserted, {@code false} if the key already exists
39+
*/
2240
public boolean insert(int key) {
2341
if (root == null) {
2442
root = new Node(key, null);
@@ -31,7 +49,6 @@ public boolean insert(int key) {
3149
}
3250

3351
parent = n;
34-
3552
boolean goLeft = n.key > key;
3653
n = goLeft ? n.left : n.right;
3754

@@ -49,8 +66,32 @@ public boolean insert(int key) {
4966
return true;
5067
}
5168

69+
/**
70+
* Deletes a key from the AVL tree.
71+
*
72+
* @param delKey the key to be deleted
73+
*/
74+
public void delete(int delKey) {
75+
if (root == null) {
76+
return;
77+
}
78+
79+
// Find the node to be deleted
80+
Node node = root;
81+
Node child = root;
82+
while (child != null) {
83+
node = child;
84+
child = delKey >= node.key ? node.right : node.left;
85+
if (delKey == node.key) {
86+
delete(node);
87+
return;
88+
}
89+
}
90+
}
91+
5292
private void delete(Node node) {
5393
if (node.left == null && node.right == null) {
94+
// Leaf node
5495
if (node.parent == null) {
5596
root = null;
5697
} else {
@@ -64,6 +105,8 @@ private void delete(Node node) {
64105
}
65106
return;
66107
}
108+
109+
// Node has one or two children
67110
Node child;
68111
if (node.left != null) {
69112
child = node.left;
@@ -80,26 +123,49 @@ private void delete(Node node) {
80123
delete(child);
81124
}
82125

83-
public void delete(int delKey) {
84-
if (root == null) {
85-
return;
126+
/**
127+
* Returns a list of balance factors for each node in the tree.
128+
*
129+
* @return a list of integers representing the balance factors of the nodes
130+
*/
131+
public List<Integer> returnBalance() {
132+
List<Integer> balances = new ArrayList<>();
133+
returnBalance(root, balances);
134+
return balances;
135+
}
136+
137+
private void returnBalance(Node n, List<Integer> balances) {
138+
if (n != null) {
139+
returnBalance(n.left, balances);
140+
balances.add(n.getBalance());
141+
returnBalance(n.right, balances);
86142
}
87-
Node node = root;
88-
Node child = root;
143+
}
89144

90-
while (child != null) {
91-
node = child;
92-
child = delKey >= node.key ? node.right : node.left;
93-
if (delKey == node.key) {
94-
delete(node);
95-
return;
96-
}
145+
/**
146+
* Searches for a key in the AVL tree.
147+
*
148+
* @param key the key to be searched
149+
* @return true if the key is found, false otherwise
150+
*/
151+
public boolean search(int key) {
152+
Node result = searchHelper(this.root, key);
153+
return result != null;
154+
}
155+
156+
private Node searchHelper(Node root, int key) {
157+
if (root == null || root.key == key) {
158+
return root;
97159
}
160+
161+
if (root.key > key) {
162+
return searchHelper(root.left, key);
163+
}
164+
return searchHelper(root.right, key);
98165
}
99166

100167
private void rebalance(Node n) {
101168
setBalance(n);
102-
103169
if (n.balance == -2) {
104170
if (height(n.left.left) >= height(n.left.right)) {
105171
n = rotateRight(n);
@@ -143,7 +209,6 @@ private Node rotateLeft(Node a) {
143209
}
144210

145211
setBalance(a, b);
146-
147212
return b;
148213
}
149214

@@ -169,7 +234,6 @@ private Node rotateRight(Node a) {
169234
}
170235

171236
setBalance(a, b);
172-
173237
return b;
174238
}
175239

@@ -197,53 +261,9 @@ private void setBalance(Node... nodes) {
197261
}
198262
}
199263

200-
public void printBalance() {
201-
printBalance(root);
202-
}
203-
204-
private void printBalance(Node n) {
205-
if (n != null) {
206-
printBalance(n.left);
207-
System.out.printf("%s ", n.balance);
208-
printBalance(n.right);
209-
}
210-
}
211-
212264
private void reheight(Node node) {
213265
if (node != null) {
214266
node.height = 1 + Math.max(height(node.left), height(node.right));
215267
}
216268
}
217-
218-
public boolean search(int key) {
219-
Node result = searchHelper(this.root, key);
220-
return result != null;
221-
}
222-
223-
private Node searchHelper(Node root, int key) {
224-
// root is null or key is present at root
225-
if (root == null || root.key == key) {
226-
return root;
227-
}
228-
229-
// key is greater than root's key
230-
if (root.key > key) {
231-
return searchHelper(root.left, key); // call the function on the node's left child
232-
}
233-
// key is less than root's key then
234-
// call the function on the node's right child as it is greater
235-
return searchHelper(root.right, key);
236-
}
237-
238-
public static void main(String[] args) {
239-
AVLTree tree = new AVLTree();
240-
241-
System.out.println("Inserting values 1 to 10");
242-
for (int i = 1; i < 10; i++) {
243-
tree.insert(i);
244-
}
245-
246-
System.out.print("Printing balance: ");
247-
tree.printBalance();
248-
}
249269
}
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
package com.thealgorithms.datastructures.trees;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
import static org.junit.jupiter.api.Assertions.assertFalse;
5+
import static org.junit.jupiter.api.Assertions.assertTrue;
6+
7+
import java.util.List;
8+
import org.junit.jupiter.api.BeforeEach;
9+
import org.junit.jupiter.api.Test;
10+
11+
public class AVLTreeTest {
12+
private AVLTree avlTree;
13+
14+
@BeforeEach
15+
public void setUp() {
16+
avlTree = new AVLTree();
17+
}
18+
19+
@Test
20+
public void testInsert() {
21+
assertTrue(avlTree.insert(10));
22+
assertTrue(avlTree.insert(20));
23+
assertTrue(avlTree.insert(5));
24+
assertFalse(avlTree.insert(10)); // Duplicate
25+
}
26+
27+
@Test
28+
public void testSearch() {
29+
avlTree.insert(15);
30+
avlTree.insert(25);
31+
assertTrue(avlTree.search(15));
32+
assertFalse(avlTree.search(30)); // Not in the tree
33+
}
34+
35+
@Test
36+
public void testDeleteLeafNode() {
37+
avlTree.insert(10);
38+
avlTree.insert(20);
39+
avlTree.insert(30);
40+
avlTree.delete(30);
41+
assertFalse(avlTree.search(30));
42+
}
43+
44+
@Test
45+
public void testDeleteNodeWithOneChild() {
46+
avlTree.insert(20);
47+
avlTree.insert(10);
48+
avlTree.insert(30);
49+
avlTree.delete(10);
50+
assertFalse(avlTree.search(10));
51+
}
52+
53+
@Test
54+
public void testDeleteNodeWithTwoChildren() {
55+
avlTree.insert(20);
56+
avlTree.insert(10);
57+
avlTree.insert(30);
58+
avlTree.insert(25);
59+
avlTree.delete(20);
60+
assertFalse(avlTree.search(20));
61+
assertTrue(avlTree.search(30));
62+
assertTrue(avlTree.search(25));
63+
}
64+
65+
@Test
66+
public void testReturnBalance() {
67+
avlTree.insert(10);
68+
avlTree.insert(20);
69+
avlTree.insert(5);
70+
List<Integer> balances = avlTree.returnBalance();
71+
assertEquals(3, balances.size()); // There should be 3 nodes
72+
assertEquals(0, balances.get(0)); // Balance for node 5
73+
assertEquals(0, balances.get(1)); // Balance for node 10
74+
assertEquals(0, balances.get(2)); // Balance for node 20
75+
}
76+
77+
@Test
78+
public void testInsertAndRebalance() {
79+
avlTree.insert(30);
80+
avlTree.insert(20);
81+
avlTree.insert(10); // This should cause a right rotation
82+
assertTrue(avlTree.search(20));
83+
assertTrue(avlTree.search(10));
84+
assertTrue(avlTree.search(30));
85+
}
86+
87+
@Test
88+
public void testComplexInsertionAndDeletion() {
89+
avlTree.insert(30);
90+
avlTree.insert(20);
91+
avlTree.insert(10);
92+
avlTree.insert(25);
93+
avlTree.insert(5);
94+
avlTree.insert(15);
95+
96+
avlTree.delete(20); // Test deletion
97+
assertFalse(avlTree.search(20));
98+
assertTrue(avlTree.search(30));
99+
assertTrue(avlTree.search(25));
100+
}
101+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy