Skip to content

Commit 0ebac5f

Browse files
committed
Fix FenwickTree test filename and add documentation link
1 parent e3d6222 commit 0ebac5f

3 files changed

Lines changed: 184 additions & 1 deletion

File tree

‎src/main/java/com/thealgorithms/datastructures/trees/FenwickTree.java‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
package com.thealgorithms.datastructures.trees;
22

3-
/** Fenwick Tree for point updates and prefix-sum queries in O(log n). */
3+
/**
4+
* Fenwick Tree for point updates and prefix-sum queries in O(log n).
5+
*
6+
* @see <a href="https://cp-algorithms.com/data_structures/fenwick.html">Fenwick Tree</a>
7+
*/
48
public class FenwickTree {
59

610
private final int n;

src/test/java/com/thealgorithms/datastructures/trees/FenwickTree.java renamed to src/test/java/com/thealgorithms/datastructures/trees/FenwickTreeTest.java

File renamed without changes.

‎ts"‎

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
diff --git a/src/main/java/com/thealgorithms/datastructures/trees/FenwickTree.java b/src/main/java/com/thealgorithms/datastructures/trees/FenwickTree.java
2+
index 5378a01..be8a92e 100644
3+
--- a/src/main/java/com/thealgorithms/datastructures/trees/FenwickTree.java
4+
+++ b/src/main/java/com/thealgorithms/datastructures/trees/FenwickTree.java
5+
@@ -1,29 +1,33 @@
6+
package com.thealgorithms.datastructures.trees;
7+

8+
+/** Fenwick Tree for point updates and prefix-sum queries in O(log n). */
9+
public class FenwickTree {
10+

11+
- private int n;
12+
- private int[] fenTree;
13+
+ private final int n;
14+
+ private final int[] fenTree;
15+

16+
- /* Constructor which takes the size of the array as a parameter */
17+
+ /** Creates a Fenwick tree with n elements, all initialized to zero. */
18+
public FenwickTree(int n) {
19+
+ if (n < 0) {
20+
+ throw new IllegalArgumentException("Size must be non-negative");
21+
+ }
22+
this.n = n;
23+
this.fenTree = new int[n + 1];
24+
}
25+

26+
- /* A function which will add the element val at index i*/
27+
+ /** Adds val to the element at index i. */
28+
public void update(int i, int val) {
29+
- // As index starts from 0, increment the index by 1
30+
- i += 1;
31+
+ checkIndex(i);
32+
+ i += 1; // Convert to the internal 1-based index
33+
while (i <= n) {
34+
fenTree[i] += val;
35+
i += i & (-i);
36+
}
37+
}
38+

39+
- /* A function which will return the cumulative sum from index 1 to index i*/
40+
+ /** Returns the sum of elements from index 0 to i. */
41+
public int query(int i) {
42+
- // As index starts from 0, increment the index by 1
43+
+ checkIndex(i);
44+
i += 1;
45+
int cumSum = 0;
46+
while (i > 0) {
47+
@@ -32,4 +36,11 @@ public class FenwickTree {
48+
}
49+
return cumSum;
50+
}
51+
+
52+
+ // Check that the index is within the valid range.
53+
+ private void checkIndex(int i) {
54+
+ if (i < 0 || i >= n) {
55+
+ throw new IndexOutOfBoundsException("Index " + i + " out of bounds for size " + n);
56+
+ }
57+
+ }
58+
}
59+
diff --git a/src/test/java/com/thealgorithms/datastructures/trees/FenwickTree.java b/src/test/java/com/thealgorithms/datastructures/trees/FenwickTree.java
60+
new file mode 100644
61+
index 0000000..47ef568
62+
--- /dev/null
63+
+++ b/src/test/java/com/thealgorithms/datastructures/trees/FenwickTree.java
64+
@@ -0,0 +1,115 @@
65+
+package com.thealgorithms.datastructures.trees;
66+
+
67+
+import static org.junit.jupiter.api.Assertions.assertEquals;
68+
+import static org.junit.jupiter.api.Assertions.assertThrows;
69+
+
70+
+import java.util.Random;
71+
+import org.junit.jupiter.api.Test;
72+
+
73+
+class FenwickTreeTest {
74+
+
75+
+ @Test
76+
+ void queryOnFreshTreeReturnsZero() {
77+
+ FenwickTree tree = new FenwickTree(5);
78+
+ for (int i = 0; i < 5; i++) {
79+
+ assertEquals(0, tree.query(i));
80+
+ }
81+
+ }
82+
+
83+
+ @Test
84+
+ void singleElementTree() {
85+
+ FenwickTree tree = new FenwickTree(1);
86+
+ tree.update(0, 7);
87+
+ assertEquals(7, tree.query(0));
88+
+ }
89+
+
90+
+ @Test
91+
+ void prefixSumsAfterUpdates() {
92+
+ FenwickTree tree = new FenwickTree(5);
93+
+ int[] values = {3, 2, -1, 6, 5};
94+
+ for (int i = 0; i < values.length; i++) {
95+
+ tree.update(i, values[i]);
96+
+ }
97+
+ assertEquals(3, tree.query(0));
98+
+ assertEquals(5, tree.query(1));
99+
+ assertEquals(4, tree.query(2));
100+
+ assertEquals(10, tree.query(3));
101+
+ assertEquals(15, tree.query(4));
102+
+ }
103+
+
104+
+ @Test
105+
+ void repeatedUpdatesOnSameIndexAccumulate() {
106+
+ FenwickTree tree = new FenwickTree(4);
107+
+ tree.update(2, 5);
108+
+ tree.update(2, 3);
109+
+ tree.update(2, -2);
110+
+ assertEquals(0, tree.query(1));
111+
+ assertEquals(6, tree.query(2));
112+
+ assertEquals(6, tree.query(3));
113+
+ }
114+
+
115+
+ @Test
116+
+ void negativeValues() {
117+
+ FenwickTree tree = new FenwickTree(3);
118+
+ tree.update(0, -4);
119+
+ tree.update(1, -6);
120+
+ tree.update(2, 10);
121+
+ assertEquals(-4, tree.query(0));
122+
+ assertEquals(-10, tree.query(1));
123+
+ assertEquals(0, tree.query(2));
124+
+ }
125+
+
126+
+ @Test
127+
+ void nonPowerOfTwoSize() {
128+
+ int size = 13;
129+
+ FenwickTree tree = new FenwickTree(size);
130+
+ for (int i = 0; i < size; i++) {
131+
+ tree.update(i, 1);
132+
+ }
133+
+ for (int i = 0; i < size; i++) {
134+
+ assertEquals(i + 1, tree.query(i));
135+
+ }
136+
+ }
137+
+
138+
+ @Test
139+
+ void matchesNaivePrefixSumOnRandomData() {
140+
+ Random random = new Random(42);
141+
+ int size = 100;
142+
+ FenwickTree tree = new FenwickTree(size);
143+
+ int[] naive = new int[size];
144+
+
145+
+ for (int step = 0; step < 500; step++) {
146+
+ int index = random.nextInt(size);
147+
+ int delta = random.nextInt(21) - 10;
148+
+ tree.update(index, delta);
149+
+ naive[index] += delta;
150+
+ }
151+
+
152+
+ int running = 0;
153+
+ for (int i = 0; i < size; i++) {
154+
+ running += naive[i];
155+
+ assertEquals(running, tree.query(i), "Mismatch at index " + i);
156+
+ }
157+
+ }
158+
+
159+
+ @Test
160+
+ void zeroSizeTreeRejectsAnyIndex() {
161+
+ FenwickTree tree = new FenwickTree(0);
162+
+ assertThrows(IndexOutOfBoundsException.class, () -> tree.update(0, 1));
163+
+ assertThrows(IndexOutOfBoundsException.class, () -> tree.query(0));
164+
+ }
165+
+
166+
+ @Test
167+
+ void negativeSizeThrows() {
168+
+ assertThrows(IllegalArgumentException.class, () -> new FenwickTree(-1));
169+
+ }
170+
+
171+
+ @Test
172+
+ void outOfBoundsIndicesThrow() {
173+
+ FenwickTree tree = new FenwickTree(5);
174+
+ assertThrows(IndexOutOfBoundsException.class, () -> tree.update(-1, 1));
175+
+ assertThrows(IndexOutOfBoundsException.class, () -> tree.update(5, 1));
176+
+ assertThrows(IndexOutOfBoundsException.class, () -> tree.query(-1));
177+
+ assertThrows(IndexOutOfBoundsException.class, () -> tree.query(5));
178+
+ }
179+
+}

0 commit comments

Comments
 (0)