package com.freetymekiyan.algorithms.datastructures;
/**
* Binary Indexed Tree is represented as an array. Let the array be BITree[]. Each node of Binary Indexed Tree stores
* sum of some elements of given array. Size of Binary Indexed Tree is equal to n where n is size of input array. In
* the below code, we have used size as n+1 for ease of implementation.
* <p>
* Operations
* <p>
* getSum(index): Returns sum of arr[0..index]
* <p>
* update(index, val): Updates BIT for operation arr[index] += val
* <p>
* http://www.geeksforgeeks.org/binary-indexed-tree-or-fenwick-tree-2/
*/
public class BinaryIndexedTree {
private final int size;
private final int[] BITree;
private BinaryIndexedTree tree;
public BinaryIndexedTree(int[] arr, int len) {
if (arr == null || arr.length == 0) {
throw new NullPointerException("Given array is null or empty");
}
if (len > arr.length) {
throw new IllegalArgumentException("Given length is larger than array size");
}
size = len;
BITree = new int[size + 1];
for (int i = 1; i <= size; i++) {
BITree[i] = 0;
}
// Store the actual values in BITree[] using update()
for (int i = 0; i < size; i++) {
update(i, arr[i]);
}
}
/**
* 1) Initialize sum as 0 and index as index+1.
* 2) Do following while index is greater than 0.
* ...a) Add BITree[index] to sum
* ...b) Go to parent of BITree[index]. Parent can be obtained by removing
* the last set bit from index, i.e., index = index - (index & (-index))
* 3) Return sum.
*/
public int getSum(int index) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException("Index " + index + " out of range.");
}
int sum = 0;
index += 1;
while (index > 0) {
sum += BITree[index];
index -= index & (-index); // Move index to parent node
}
return sum;
}
/**
* Get range sum, inclusive
*/
public int getRangeSum(int from, int to) {
if (from > to) {
throw new IllegalArgumentException("from: " + from + " is larger than to: " + to);
}
if (from < 0 || from >= size || to < 0 || to >= size) {
throw new IndexOutOfBoundsException("from: " + from + " to: " + to + " should be within [0, " + size + "]");
}
return getSum(to) - getSum(from - 1);
}
/**
* 1) Initialize index as index+1.
* 2) Do following while index is smaller than or equal to n.
* ...a) Add value to BITree[index]
* ...b) Go to parent of BITree[index]. Parent can be obtained by removing
* the last set bit from index, i.e., index = index + (index & (-index))
*
* @param index index of the position to be updated
* @param value value to be added
*/
public void update(int index, int value) {
if (index < 0 || index >= size) {
throw new ArrayIndexOutOfBoundsException("Index " + index + " out of range.");
}
index += 1;
while (index <= size) {
BITree[index] += value;
index += index & (-index); // Move index to parent node in update View
}
}
}