Skip to content

Commit ced31be

Browse files
committed
Added Binary Search Tree with JUnit 5 tests
1 parent a4cf6e3 commit ced31be

File tree

2 files changed

+329
-0
lines changed

2 files changed

+329
-0
lines changed
Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
package com.thealgorithms.tree;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
6+
/**
7+
* Binary Search Tree (BST) Implementation in Java.
8+
*
9+
* Supports: - insert(key): Insert a key into the BST - delete(key): Delete a
10+
* key from the BST - search(key): Search if a key exists in the BST -
11+
* findMin(): Find the minimum key - findMax(): Find the maximum key -
12+
* inorder(), preorder(), postorder(): Traversals (print) - inorderList(),
13+
* preorderList(), postorderList(): Traversals for testing (return
14+
* List<Integer>)
15+
*
16+
* Notes: - Duplicate keys are ignored
17+
*/
18+
public class BinarySearchTree {
19+
20+
/**
21+
* Node class representing each node in BST
22+
*/
23+
private static class Node {
24+
25+
int key;
26+
Node left;
27+
Node right;
28+
29+
Node(int key) {
30+
this.key = key;
31+
}
32+
}
33+
34+
private Node root;
35+
36+
/**
37+
* Insert a key into the BST
38+
*/
39+
public void insert(int key) {
40+
root = insertRec(root, key);
41+
}
42+
43+
private Node insertRec(Node root, int key) {
44+
if (root == null) {
45+
return new Node(key);
46+
}
47+
if (key < root.key) {
48+
root.left = insertRec(root.left, key);
49+
}else if (key > root.key) {
50+
root.right = insertRec(root.right, key);
51+
}
52+
return root; // duplicates ignored
53+
}
54+
55+
/**
56+
* Search for a key in the BST
57+
*/
58+
public boolean search(int key) {
59+
return searchRec(root, key);
60+
}
61+
62+
private boolean searchRec(Node root, int key) {
63+
if (root == null) {
64+
return false;
65+
}
66+
if (root.key == key) {
67+
return true;
68+
}
69+
return key < root.key ? searchRec(root.left, key) : searchRec(root.right, key);
70+
}
71+
72+
/**
73+
* Delete a key from the BST
74+
*/
75+
public void delete(int key) {
76+
root = deleteRec(root, key);
77+
}
78+
79+
private Node deleteRec(Node root, int key) {
80+
if (root == null) {
81+
return null;
82+
}
83+
84+
if (key < root.key) {
85+
root.left = deleteRec(root.left, key);
86+
}else if (key > root.key) {
87+
root.right = deleteRec(root.right, key);
88+
}else {
89+
// Node found
90+
if (root.left == null && root.right == null) {
91+
return null; // no child
92+
93+
}if (root.left == null) {
94+
return root.right; // one child
95+
96+
}if (root.right == null) {
97+
return root.left; // one child
98+
}
99+
// two children: replace with inorder successor
100+
int minValue = findMinRec(root.right);
101+
root.key = minValue;
102+
root.right = deleteRec(root.right, minValue);
103+
}
104+
return root;
105+
}
106+
107+
/**
108+
* Inorder traversal (print)
109+
*/
110+
public void inorder() {
111+
inorderRec(root);
112+
System.out.println();
113+
}
114+
115+
private void inorderRec(Node node) {
116+
if (node != null) {
117+
inorderRec(node.left);
118+
System.out.print(node.key + " ");
119+
inorderRec(node.right);
120+
}
121+
}
122+
123+
/**
124+
* Preorder traversal (print)
125+
*/
126+
public void preorder() {
127+
preorderRec(root);
128+
System.out.println();
129+
}
130+
131+
private void preorderRec(Node node) {
132+
if (node != null) {
133+
System.out.print(node.key + " ");
134+
preorderRec(node.left);
135+
preorderRec(node.right);
136+
}
137+
}
138+
139+
/**
140+
* Postorder traversal (print)
141+
*/
142+
public void postorder() {
143+
postorderRec(root);
144+
System.out.println();
145+
}
146+
147+
private void postorderRec(Node node) {
148+
if (node != null) {
149+
postorderRec(node.left);
150+
postorderRec(node.right);
151+
System.out.print(node.key + " ");
152+
}
153+
}
154+
155+
/**
156+
* Inorder traversal returning a list (for testing)
157+
*/
158+
public List<Integer> inorderList() {
159+
List<Integer> list = new ArrayList<>();
160+
inorderListRec(root, list);
161+
return list;
162+
}
163+
164+
private void inorderListRec(Node node, List<Integer> list) {
165+
if (node == null) {
166+
return;
167+
}
168+
inorderListRec(node.left, list);
169+
list.add(node.key);
170+
inorderListRec(node.right, list);
171+
}
172+
173+
/**
174+
* Preorder traversal returning a list (for testing)
175+
*/
176+
public List<Integer> preorderList() {
177+
List<Integer> list = new ArrayList<>();
178+
preorderListRec(root, list);
179+
return list;
180+
}
181+
182+
private void preorderListRec(Node node, List<Integer> list) {
183+
if (node == null) {
184+
return;
185+
}
186+
list.add(node.key);
187+
preorderListRec(node.left, list);
188+
preorderListRec(node.right, list);
189+
}
190+
191+
/**
192+
* Postorder traversal returning a list (for testing)
193+
*/
194+
public List<Integer> postorderList() {
195+
List<Integer> list = new ArrayList<>();
196+
postorderListRec(root, list);
197+
return list;
198+
}
199+
200+
private void postorderListRec(Node node, List<Integer> list) {
201+
if (node == null) {
202+
return;
203+
}
204+
postorderListRec(node.left, list);
205+
postorderListRec(node.right, list);
206+
list.add(node.key);
207+
}
208+
209+
/**
210+
* Find minimum key
211+
*/
212+
public int findMin() {
213+
if (root == null) {
214+
throw new IllegalStateException("Tree is empty");
215+
}
216+
return findMinRec(root);
217+
}
218+
219+
private int findMinRec(Node node) {
220+
while (node.left != null) {
221+
node = node.left;
222+
}
223+
return node.key;
224+
}
225+
226+
/**
227+
* Find maximum key
228+
*/
229+
public int findMax() {
230+
if (root == null) {
231+
throw new IllegalStateException("Tree is empty");
232+
}
233+
return findMaxRec(root);
234+
}
235+
236+
private int findMaxRec(Node node) {
237+
while (node.right != null) {
238+
node = node.right;
239+
}
240+
return node.key;
241+
}
242+
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package com.thealgorithms.tree;
2+
3+
import java.util.Arrays;
4+
import java.util.List;
5+
6+
import static org.junit.jupiter.api.Assertions.assertEquals;
7+
import static org.junit.jupiter.api.Assertions.assertFalse;
8+
import static org.junit.jupiter.api.Assertions.assertTrue;
9+
import org.junit.jupiter.api.BeforeEach;
10+
import org.junit.jupiter.api.Test;
11+
12+
/**
13+
* Unit tests for BinarySearchTree. Tests: - insert and search - delete (leaf,
14+
* one child, two children) - findMin and findMax - inorder, preorder, postorder
15+
* traversals
16+
*/
17+
class BinarySearchTreeTest {
18+
19+
private BinarySearchTree bst;
20+
21+
@BeforeEach
22+
void setUp() {
23+
bst = new BinarySearchTree();
24+
bst.insert(10);
25+
bst.insert(5);
26+
bst.insert(15);
27+
}
28+
29+
@Test
30+
void testSearch() {
31+
assertTrue(bst.search(10));
32+
assertTrue(bst.search(5));
33+
assertTrue(bst.search(15));
34+
assertFalse(bst.search(7));
35+
}
36+
37+
@Test
38+
void testFindMinMax() {
39+
assertEquals(5, bst.findMin());
40+
assertEquals(15, bst.findMax());
41+
}
42+
43+
@Test
44+
void testDeleteLeafNode() {
45+
bst.delete(5);
46+
assertFalse(bst.search(5));
47+
assertTrue(bst.search(10));
48+
assertTrue(bst.search(15));
49+
}
50+
51+
@Test
52+
void testDeleteNodeWithOneChild() {
53+
bst.insert(12);
54+
bst.delete(15);
55+
assertFalse(bst.search(15));
56+
assertTrue(bst.search(12));
57+
}
58+
59+
@Test
60+
void testDeleteNodeWithTwoChildren() {
61+
bst.insert(12);
62+
bst.insert(20);
63+
bst.delete(10);
64+
assertFalse(bst.search(10));
65+
assertTrue(bst.search(5));
66+
assertTrue(bst.search(12));
67+
assertTrue(bst.search(15));
68+
}
69+
70+
@Test
71+
void testInorderTraversal() {
72+
List<Integer> expected = Arrays.asList(5, 10, 15);
73+
assertEquals(expected, bst.inorderList());
74+
}
75+
76+
@Test
77+
void testPreorderTraversal() {
78+
List<Integer> expected = Arrays.asList(10, 5, 15);
79+
assertEquals(expected, bst.preorderList());
80+
}
81+
82+
@Test
83+
void testPostorderTraversal() {
84+
List<Integer> expected = Arrays.asList(5, 15, 10);
85+
assertEquals(expected, bst.postorderList());
86+
}
87+
}

0 commit comments

Comments
 (0)