Skip to content

Commit bc6dd57

Browse files
committed
chore: cleanup readme and tests
1 parent 50cf843 commit bc6dd57

File tree

3 files changed

+140
-29
lines changed

3 files changed

+140
-29
lines changed

src/main/java/dataStructures/bTree/BTree.java

Lines changed: 96 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
package dataStructures.bTree;
22

3+
import java.util.ArrayList;
4+
import java.util.LinkedList;
5+
import java.util.List;
6+
import java.util.Queue;
7+
38
/** This BTree implementation is a simplified implementation, which supports the basic search, insert, delete and
49
* in-order traversal operations. It is not designed to cover edge cases.
510
*/
@@ -144,32 +149,6 @@ private void insertNonFull(BTreeNode x, int key) {
144149
}
145150
}
146151

147-
/**
148-
* Prints the keys of the B-tree level by level.
149-
*/
150-
public void printBTree() {
151-
if (root != null) {
152-
printBTree(root, 0);
153-
}
154-
}
155-
156-
private void printBTree(BTreeNode node, int level) {
157-
System.out.println("Level " + level + ": " + node.keyCount + " keys");
158-
159-
for (int i = 0; i < node.keyCount; i++) {
160-
System.out.print(node.keys[i] + " ");
161-
}
162-
System.out.println();
163-
164-
if (!node.leaf) {
165-
for (int i = 0; i <= node.keyCount; i++) {
166-
if (node.children[i] != null) {
167-
printBTree(node.children[i], level + 1);
168-
}
169-
}
170-
}
171-
}
172-
173152
/**
174153
* Deletes the specified key from the B-tree.
175154
* @param key key to be deleted
@@ -361,4 +340,95 @@ private void borrowFromRight(BTreeNode x, int i) {
361340
sibling.keyCount--;
362341
}
363342

343+
/**
344+
* Returns the level order traversal of the B Tree.
345+
* @return An array containing the level order traversal of the B Tree.
346+
*/
347+
public Object[] levelOrderTraversal() {
348+
List<Integer> result = new ArrayList<>();
349+
350+
if (root == null) {
351+
return result.toArray(); // Return an empty list for an empty tree
352+
}
353+
354+
Queue<BTreeNode> queue = new LinkedList<>();
355+
queue.offer(root);
356+
357+
while (!queue.isEmpty()) {
358+
int levelSize = queue.size();
359+
360+
for (int i = 0; i < levelSize; i++) {
361+
BTreeNode current = queue.poll();
362+
363+
// Process current node
364+
for (int j = 0; j < current.keyCount; j++) {
365+
result.add(current.keys[j]);
366+
}
367+
368+
// Enqueue children if not a leaf
369+
if (!current.leaf) {
370+
for (int j = 0; j <= current.keyCount; j++) {
371+
if (current.children[j] != null) {
372+
queue.offer(current.children[j]);
373+
}
374+
}
375+
}
376+
}
377+
}
378+
379+
return result.toArray();
380+
}
381+
382+
/**
383+
* Returns the preorder traversal of the B Tree.
384+
* @return An array containing the preorder traversal of the B Tree.
385+
*/
386+
public Object[] preOrderTraversal() {
387+
List<Integer> result = new ArrayList<>();
388+
preOrderTraversal(root, result);
389+
return result.toArray();
390+
}
391+
392+
private void preOrderTraversal(BTreeNode node, List<Integer> result) {
393+
if (node != null) {
394+
// Process current node
395+
for (int i = 0; i < node.keyCount; i++) {
396+
result.add(node.keys[i]);
397+
}
398+
399+
// Recursively traverse children
400+
if (!node.leaf) {
401+
for (int i = 0; i <= node.keyCount; i++) {
402+
preOrderTraversal(node.children[i], result);
403+
}
404+
}
405+
}
406+
}
407+
408+
/**
409+
* Debugging method: Prints the keys of the B-tree level by level.
410+
*/
411+
public void printBTree() {
412+
if (root != null) {
413+
printBTree(root, 0);
414+
}
415+
}
416+
417+
private void printBTree(BTreeNode node, int level) {
418+
System.out.println("Level " + level + ": " + node.keyCount + " keys");
419+
420+
for (int i = 0; i < node.keyCount; i++) {
421+
System.out.print(node.keys[i] + " ");
422+
}
423+
System.out.println();
424+
425+
if (!node.leaf) {
426+
for (int i = 0; i <= node.keyCount; i++) {
427+
if (node.children[i] != null) {
428+
printBTree(node.children[i], level + 1);
429+
}
430+
}
431+
}
432+
}
433+
364434
}

src/main/java/dataStructures/bTree/README.md

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# B-Trees
22

33
## Background
4-
Is the fastest way to search for data to store them in an array, sort them and perform binary search? No. <br>
4+
Is the fastest way to search for data to store them in an array, sort them and perform binary search? No. This will
5+
incur minimally O(nlogn) sorting cost, and O(n) cost per insertion to maintain sorted order. <br>
56

67
We have seen binary search trees (BSTs), which always maintains data in sorted order. This allows us to avoid the
78
overhead of sorting before we search. However, we also learnt that unbalanced BSTs can be incredibly inefficient for
@@ -18,7 +19,7 @@ insertion, deletion and search operations.
1819

1920
Before we talk about B-trees, we first introduce its family (generalized form) - (a,b) trees. <br>
2021

21-
- In an (a,b) tree, a nd b refer to the minimum and maximum number of children of an internal node in the tree. <br>
22+
- In an (a,b) tree, a and b refer to the minimum and maximum number of children of an internal node in the tree. <br>
2223
- a and b are parameters where 2 <= a <= (b+1)/2.
2324

2425
Note that unlike binary trees, in (a,b) trees, each node can have more than 2 children and each node can store multiple
@@ -55,11 +56,12 @@ Specifically, for a non-leaf node with k keys and (k+1) children:
5556
Then:
5657
- first child t1 has key range <= v1
5758
- final child tk+1 has key range > vk
58-
- all other children ti have key range (vi-1, vi)
59+
- all other children ti have key range (vi-1, vi]
5960

6061
Rule #3: Leaf depth
6162

6263
All leaf nodes must be at the same depth from root.
64+
- This property forces the tree to be balanced.
6365

6466
## Complexity Analysis
6567

@@ -100,5 +102,26 @@ Image Source: https://www.geeksforgeeks.org/insert-operation-in-b-tree/
100102
The delete operation has a similar idea as the insert operation, but involves a lot more edge cases. If you are
101103
interested to learn about it, you can read more [here](https://www.geeksforgeeks.org/delete-operation-in-b-tree/).
102104

105+
## Application
106+
There are many uses of B-Trees but the most common is their utility in database management systems in handling large
107+
datasets by optimizing disk accesses.
108+
109+
Large amounts of data have to be stored on the disk. But disk I/O operations are slow and not knowing where to look
110+
for the data can drastically worsen search time. B-Tree is used as an index structure to efficiently locate the
111+
desired data. Note, the B-Tree itself can be partially stored in RAM (higher levels) and and partially on disk
112+
(lower, less freq accessed levels).
113+
114+
Consider a database of all the CS modules offered in NUS. Suppose there is a column "Code" (module code) in the
115+
"CS Modules" table. If the database has a B-Tree index on the "Code" column, the keys in the B-Tree would be the
116+
module code of all CS modules offered.
117+
118+
Each key in the B-Tree is associated with a pointer, that points to the location on the disk where the corresponding
119+
data can be found. For e.g., a key for "CS2040s" would have a pointer to the disk location(s) where the row(s)
120+
(i.e. data) with "CS2040s" is stored. This efficient querying allows the database quickly navigate through the keys
121+
and find the disk location of the desired data without having to scan the whole "CS Modules" table.
122+
123+
The choice of t will impact the height of the tree, and hence how fast the query is. Trade-off would be space, as a
124+
higher t means more keys in each node and they would have to be (if not already) loaded to RAM.
125+
103126
## References
104127
This description heavily references CS2040S Recitation Sheet 4.

src/test/java/dataStructures/bTree/BTreeTest.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package dataStructures.bTree;
22

33
import org.junit.Test;
4+
import java.util.ArrayList;
5+
import java.util.Arrays;
46

7+
import static org.junit.Assert.assertArrayEquals;
58
import static org.junit.Assert.assertEquals;
69

710
public class BTreeTest {
@@ -14,6 +17,11 @@ public void test_BTree() {
1417
bTree.insert(key);
1518
}
1619

20+
Object[] expectedLevelOrderTraversal1 = {5, 8, 1, 2, 3, 4, 6, 7, 9, 10, 11, 12};
21+
Object[] expectedPreOrderTraversal1 = {5, 8, 1, 2, 3, 4, 6, 7, 9, 10, 11, 12};
22+
assertArrayEquals(bTree.levelOrderTraversal(), expectedLevelOrderTraversal1);
23+
assertArrayEquals(bTree.preOrderTraversal(), expectedPreOrderTraversal1);
24+
1725
assertEquals(true, bTree.search(8));
1826
assertEquals(true, bTree.search(4));
1927
assertEquals(true, bTree.search(7));
@@ -23,8 +31,18 @@ public void test_BTree() {
2331
bTree.delete(7);
2432
assertEquals(false, bTree.search(7));
2533

34+
Object[] expectedLevelOrderTraversal2 = {4, 8, 1, 2, 3, 5, 6, 9, 10, 11, 12};
35+
Object[] expectedPreOrderTraversal2 = {4, 8, 1, 2, 3, 5, 6, 9, 10, 11, 12};
36+
assertArrayEquals(bTree.levelOrderTraversal(), expectedLevelOrderTraversal2);
37+
assertArrayEquals(bTree.preOrderTraversal(), expectedPreOrderTraversal2);
38+
2639
bTree.delete(4);
2740
assertEquals(false, bTree.search(4));
41+
42+
Object[] expectedLevelOrderTraversal3 = {3, 8, 1, 2, 5, 6, 9, 10, 11, 12};
43+
Object[] expectedPreOrderTraversal3 = {3, 8, 1, 2, 5, 6, 9, 10, 11, 12};
44+
assertArrayEquals(bTree.levelOrderTraversal(), expectedLevelOrderTraversal3);
45+
assertArrayEquals(bTree.preOrderTraversal(), expectedPreOrderTraversal3);
2846
}
2947

3048
}

0 commit comments

Comments
 (0)