diff --git "a/ts\"" "b/ts\"" deleted file mode 100644 index daddada971db..000000000000 --- "a/ts\"" +++ /dev/null @@ -1,179 +0,0 @@ -diff --git a/src/main/java/com/thealgorithms/datastructures/trees/FenwickTree.java b/src/main/java/com/thealgorithms/datastructures/trees/FenwickTree.java -index 5378a01..be8a92e 100644 ---- a/src/main/java/com/thealgorithms/datastructures/trees/FenwickTree.java -+++ b/src/main/java/com/thealgorithms/datastructures/trees/FenwickTree.java -@@ -1,29 +1,33 @@ - package com.thealgorithms.datastructures.trees; -  -+/** Fenwick Tree for point updates and prefix-sum queries in O(log n). */ - public class FenwickTree { -  -- private int n; -- private int[] fenTree; -+ private final int n; -+ private final int[] fenTree; -  -- /* Constructor which takes the size of the array as a parameter */ -+ /** Creates a Fenwick tree with n elements, all initialized to zero. */ - public FenwickTree(int n) { -+ if (n < 0) { -+ throw new IllegalArgumentException("Size must be non-negative"); -+ } - this.n = n; - this.fenTree = new int[n + 1]; - } -  -- /* A function which will add the element val at index i*/ -+ /** Adds val to the element at index i. */ - public void update(int i, int val) { -- // As index starts from 0, increment the index by 1 -- i += 1; -+ checkIndex(i); -+ i += 1; // Convert to the internal 1-based index - while (i <= n) { - fenTree[i] += val; - i += i & (-i); - } - } -  -- /* A function which will return the cumulative sum from index 1 to index i*/ -+ /** Returns the sum of elements from index 0 to i. */ - public int query(int i) { -- // As index starts from 0, increment the index by 1 -+ checkIndex(i); - i += 1; - int cumSum = 0; - while (i > 0) { -@@ -32,4 +36,11 @@ public class FenwickTree { - } - return cumSum; - } -+ -+ // Check that the index is within the valid range. -+ private void checkIndex(int i) { -+ if (i < 0 || i >= n) { -+ throw new IndexOutOfBoundsException("Index " + i + " out of bounds for size " + n); -+ } -+ } - } -diff --git a/src/test/java/com/thealgorithms/datastructures/trees/FenwickTree.java b/src/test/java/com/thealgorithms/datastructures/trees/FenwickTree.java -new file mode 100644 -index 0000000..47ef568 ---- /dev/null -+++ b/src/test/java/com/thealgorithms/datastructures/trees/FenwickTree.java -@@ -0,0 +1,115 @@ -+package com.thealgorithms.datastructures.trees; -+ -+import static org.junit.jupiter.api.Assertions.assertEquals; -+import static org.junit.jupiter.api.Assertions.assertThrows; -+ -+import java.util.Random; -+import org.junit.jupiter.api.Test; -+ -+class FenwickTreeTest { -+ -+ @Test -+ void queryOnFreshTreeReturnsZero() { -+ FenwickTree tree = new FenwickTree(5); -+ for (int i = 0; i < 5; i++) { -+ assertEquals(0, tree.query(i)); -+ } -+ } -+ -+ @Test -+ void singleElementTree() { -+ FenwickTree tree = new FenwickTree(1); -+ tree.update(0, 7); -+ assertEquals(7, tree.query(0)); -+ } -+ -+ @Test -+ void prefixSumsAfterUpdates() { -+ FenwickTree tree = new FenwickTree(5); -+ int[] values = {3, 2, -1, 6, 5}; -+ for (int i = 0; i < values.length; i++) { -+ tree.update(i, values[i]); -+ } -+ assertEquals(3, tree.query(0)); -+ assertEquals(5, tree.query(1)); -+ assertEquals(4, tree.query(2)); -+ assertEquals(10, tree.query(3)); -+ assertEquals(15, tree.query(4)); -+ } -+ -+ @Test -+ void repeatedUpdatesOnSameIndexAccumulate() { -+ FenwickTree tree = new FenwickTree(4); -+ tree.update(2, 5); -+ tree.update(2, 3); -+ tree.update(2, -2); -+ assertEquals(0, tree.query(1)); -+ assertEquals(6, tree.query(2)); -+ assertEquals(6, tree.query(3)); -+ } -+ -+ @Test -+ void negativeValues() { -+ FenwickTree tree = new FenwickTree(3); -+ tree.update(0, -4); -+ tree.update(1, -6); -+ tree.update(2, 10); -+ assertEquals(-4, tree.query(0)); -+ assertEquals(-10, tree.query(1)); -+ assertEquals(0, tree.query(2)); -+ } -+ -+ @Test -+ void nonPowerOfTwoSize() { -+ int size = 13; -+ FenwickTree tree = new FenwickTree(size); -+ for (int i = 0; i < size; i++) { -+ tree.update(i, 1); -+ } -+ for (int i = 0; i < size; i++) { -+ assertEquals(i + 1, tree.query(i)); -+ } -+ } -+ -+ @Test -+ void matchesNaivePrefixSumOnRandomData() { -+ Random random = new Random(42); -+ int size = 100; -+ FenwickTree tree = new FenwickTree(size); -+ int[] naive = new int[size]; -+ -+ for (int step = 0; step < 500; step++) { -+ int index = random.nextInt(size); -+ int delta = random.nextInt(21) - 10; -+ tree.update(index, delta); -+ naive[index] += delta; -+ } -+ -+ int running = 0; -+ for (int i = 0; i < size; i++) { -+ running += naive[i]; -+ assertEquals(running, tree.query(i), "Mismatch at index " + i); -+ } -+ } -+ -+ @Test -+ void zeroSizeTreeRejectsAnyIndex() { -+ FenwickTree tree = new FenwickTree(0); -+ assertThrows(IndexOutOfBoundsException.class, () -> tree.update(0, 1)); -+ assertThrows(IndexOutOfBoundsException.class, () -> tree.query(0)); -+ } -+ -+ @Test -+ void negativeSizeThrows() { -+ assertThrows(IllegalArgumentException.class, () -> new FenwickTree(-1)); -+ } -+ -+ @Test -+ void outOfBoundsIndicesThrow() { -+ FenwickTree tree = new FenwickTree(5); -+ assertThrows(IndexOutOfBoundsException.class, () -> tree.update(-1, 1)); -+ assertThrows(IndexOutOfBoundsException.class, () -> tree.update(5, 1)); -+ assertThrows(IndexOutOfBoundsException.class, () -> tree.query(-1)); -+ assertThrows(IndexOutOfBoundsException.class, () -> tree.query(5)); -+ } -+}