Fenwick Tree
This page provides links to solutions that use the Fenwick Tree data structure.
Overview
The Fenwick Tree, also known as the Binary Indexed Tree, is a data structure that can perform range operations such as finding the total, minimum, or maximum value in time over a range of an array.
It can also perform point updates in time. However, it does not support range updates and in such cases, a segment tree should be used instead. Despite being called a tree, the Fenwick tree is actually stored as an array of elements.
Build Fenwick Tree
Let's create a fenwick tree for input array
To create a Fenwick tree, you need two functions called Get Parent and Get Child. These functions help you determine which index to update next when you add or update an element in the Fenwick tree.
Get Parent Function
Get parent function generates the parent index by adding to the last set bit from the right. Let's calculate parent of which is represented as in binary format. The first set bit from right is in position, so we add to that position as below:
Therefore, the parent of is .
- Java
public int getParent(int index) {
return index + (index & -index);
}
Get Child Function
Similarly, get_child function generates the child index by substracting from the last set bit from the right. Let's calculate child of which is represented as in binary format. The first set bit from right is in position, so we substract from that position
Therefore, the child of is .
- Java
public int getChild(int index) {
return index - (index & -index);
}
Let's begin building the Fenwick Tree by generating a new array with a length one greater than the input array and initializing all its elements to 0.
Adding first element from input array to fenwick tree.
Adding second element from input array fto fenwick tree.
Adding third element from input array to fenwick tree.
Adding fourth element from input array to fenwick tree.
Adding fifth element from input array to fenwick tree.
Adding sixth element from input array to fenwick tree.
Adding seventh element from input array to fenwick tree.
- Java
public int[] buildFenwickTree(int[] arr) {
// create a fenwickTree array
int[] fenwickTree = new int[arr.length + 1];
// add element to fenwick tree starting from index i
for(int i = 1; i < fenwickTree.length; i++)
add(arr[i - 1], i);
// return fenwick tree
return fenwickTree;
}
private void add(int element, int index) {
// adding element until end of fenwick tree is reached
while(index < fenwickTree.length) {
// add element at current index
fenwickTree[index] += element;
// get parent index of current index
index = getParent(index);
}
}
Use Fenwick Tree
Let's calculate the range sum from index to of original array. To do this, we calculate the prefix sum up to and subtract the prefix sum up to from it.
For calculating the prefix sum from index , we use the getChild function to traverse and add all the elements starting from index down to as below:
We get prefix sum from index as .
Notice how we are starting with index for calculating prefix sum from as fenwick tree array start inserting elements from index .
Similarly, let's calculate the prefix sum from index .
We get prefix sum from index as .
Therefore, range sum from index to of original array is:
- Java
public int rangeSum(int from, int to) {
prefixSum(to + 1) - prefixSum(from);
}
private int prefixSum(int element, int index) {
int sum = 0;
while(index > 0) {
// add element at current index
sum += fenwickTree[index];
// get child index of current index
index = getChild(index);
}
}
Update Fenwick Tree
The process of updating an element in a Fenwick Tree is the same as the process of adding an element to the Fenwick Tree. However, instead of adding the actual element, we add a delta value.
Let's update index in an original input array to . Delta at index is , so we start by adding starting from index in fenwick tree.
- Java
private int update(int newValue, int index) {
// calculate delta value
int delta = arr[index] - newValue;
// update value at index in input array to newValue
arr[index] = newValue;
// call add function
add(delta, index);
}
Complexity
Let's say there are elements in given input array.
Time Complexity
Time complexity for building a fewnick tree is:
Adding, updating and searching an element in a fenwick tree taks:
Space Complexity
Algorithm uses linear space for storing fenwick tree data structure.
How to Spot These Problems
You can identify fenwick tree problems if the problem requires you to:
- Quickly calculate the sum of elements from the start of an array up to a certain index.