using System; using System.Collections; using System.Collections.Generic; using System.Linq; namespace Advanced.Algorithms.DataStructures { /// /// A Fenwick Tree (binary indexed tree) implementation for prefix sum. /// public class FenwickTree : IEnumerable { private int length => tree.Length - 1; private T[] tree; private readonly T[] input; /// /// Add operation on generic type. /// private readonly Func sumOperation; /// /// constructs a Fenwick tree using the specified sum operation function. /// Time complexity: O(nLog(n)). /// public FenwickTree(T[] input, Func sumOperation) { if (input == null || sumOperation == null) { throw new ArgumentNullException(); } this.input = input.Clone() as T[]; this.sumOperation = sumOperation; construct(input); } /// /// Construct Fenwick tree from input array. /// private void construct(T[] input) { tree = new T[input.Length + 1]; for (var i = 0; i < input.Length; i++) { var j = i + 1; while (j < input.Length) { tree[j] = sumOperation(tree[j], input[i]); j = getNextIndex(j); } } } /// /// Gets the prefix sum from 0 till the given end index. /// Time complexity: O(log(n)). /// public T PrefixSum(int endIndex) { if (endIndex < 0 || endIndex > length - 1) { throw new ArgumentException(); } var sum = default(T); var currentIndex = endIndex + 1; while (currentIndex > 0) { sum = sumOperation(sum, tree[currentIndex]); currentIndex = getParentIndex(currentIndex); } return sum; } /// /// Get index of next sibling . /// private int getNextIndex(int currentIndex) { //add current index with //twos complimant of currentIndex AND with currentIndex return currentIndex + (currentIndex & (-currentIndex)); } /// /// Get parent node index. /// private int getParentIndex(int currentIndex) { //substract current index with //twos complimant of currentIndex AND with currentIndex return currentIndex - (currentIndex & (-currentIndex)); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public IEnumerator GetEnumerator() { return input.Select(x=>x).GetEnumerator(); } } }