|
1 | 1 | /**
|
2 | 2 | * @file
|
3 |
| - * @brief Fenwick tree |
| 3 | + * @brief [Fenwick Tree](https://en.wikipedia.org/wiki/Fenwick_tree) algorithm |
| 4 | + * implementation |
| 5 | + * @details |
| 6 | + * _From Wikipedia, the free encyclopedia._ |
4 | 7 | *
|
5 |
| - * A Fenwick tree or binary indexed tree is a data structure |
6 |
| - * that can efficiently update elements and calculate |
7 |
| - * prefix sums in a table of numbers. |
| 8 | + * A Fenwick tree or binary indexed tree (BIT) is a clever implementation of a |
| 9 | + * datastructure called bionomal tree. It can update values and solve range |
| 10 | + * queries with operations that is; commulative, associative and has an |
| 11 | + * inverse for this type of element. It can also solve immutable range queries |
| 12 | + * (min/max), when operations only are associative over this type of element. |
| 13 | + * Some of these restrictions can be removed, by storing redunant information; |
| 14 | + * like in max/min range queries. |
| 15 | + * |
| 16 | + * @author [Mateusz Grzegorzek](https://github.com/mateusz-grzegorzek) |
| 17 | + * @author [David Leal](https://github.com/Panquesito7) |
8 | 18 | */
|
9 |
| -#include <cassert> |
10 |
| -#include <iostream> |
11 |
| -#include <vector> |
| 19 | + |
| 20 | +#include <cassert> /// for assert |
| 21 | +#include <iostream> /// for IO operations |
| 22 | +#include <vector> /// for std::vector |
12 | 23 |
|
13 | 24 | /**
|
14 |
| - * n --> No. of elements present in input array. |
15 |
| - * bit[0..n] --> Array that represents Binary Indexed Tree. |
| 25 | + * @namespace |
| 26 | + * @brief Range Queries |
16 | 27 | */
|
17 |
| -class FenwickTree { |
18 |
| - int n; |
19 |
| - std::vector<int> bit; |
| 28 | +namespace range_queries { |
| 29 | +/** |
| 30 | + * @brief The class that initializes the Fenwick Tree. |
| 31 | + */ |
| 32 | +class fenwick_tree { |
| 33 | + size_t n = 0; ///< No. of elements present in input array |
| 34 | + std::vector<int> bit{}; ///< Array that represents Binary Indexed Tree. |
20 | 35 |
|
21 |
| - /** Returns the highest power of two which is not more than x */ |
| 36 | + /** |
| 37 | + * @brief Returns the highest power of two which is not more than `x`. |
| 38 | + * @param x Index of element in original array. |
| 39 | + * @return Offset of index. |
| 40 | + */ |
22 | 41 | inline int offset(int x) { return (x & (-x)); }
|
23 |
| - |
24 | 42 | public:
|
25 |
| - /** Constructor |
26 |
| - * \param[in] arr --> Input array for which prefix sum is evaluated. |
| 43 | + /** |
| 44 | + * @brief Class Constructor |
| 45 | + * @tparam T the type of the array |
| 46 | + * @param[in] arr Input array for which prefix sum is evaluated. |
| 47 | + * @return void |
27 | 48 | */
|
28 |
| - explicit FenwickTree(const std::vector<int>& arr) { |
29 |
| - n = arr.size(); |
| 49 | + template <typename T> |
| 50 | + explicit fenwick_tree(const std::vector<T>& arr) : n(arr.size()) { |
30 | 51 | bit.assign(n + 1, 0);
|
31 | 52 | for (int i = 0; i < n; ++i) {
|
32 | 53 | update(i, arr[i]);
|
33 | 54 | }
|
34 | 55 | }
|
35 | 56 |
|
36 |
| - /** Constructor |
37 |
| - * \param[in] x --> Size of array that represents Binary Indexed Tree. |
| 57 | + /** |
| 58 | + * @brief Class Constructor |
| 59 | + * @tparam T the type of the variable |
| 60 | + * @param[in] x Size of array that represents Binary Indexed Tree. |
| 61 | + * @return void |
38 | 62 | */
|
39 |
| - explicit FenwickTree(int x) { |
40 |
| - n = x; |
41 |
| - bit.assign(n + 1, 0); |
42 |
| - } |
| 63 | + template <typename T> |
| 64 | + explicit fenwick_tree(T x) : n(x) { bit.assign(n + 1, 0); } |
43 | 65 |
|
44 |
| - /** Add val at id */ |
45 |
| - void update(int id, int val) { |
| 66 | + /** |
| 67 | + * @brief Updates the value of an element in original array and |
| 68 | + * accordingly updates the values in BIT array. |
| 69 | + * @tparam T the type of the variables |
| 70 | + * @param id Index of element in original array. |
| 71 | + * @param val Value with which element's value is updated. |
| 72 | + * @return void |
| 73 | + */ |
| 74 | + template <typename T> |
| 75 | + void update(T id, T val) { |
46 | 76 | id++;
|
47 | 77 | while (id <= n) {
|
48 | 78 | bit[id] += val;
|
49 | 79 | id += offset(id);
|
50 | 80 | }
|
51 | 81 | }
|
52 | 82 |
|
53 |
| - /** Get prefix sum upto id */ |
54 |
| - int sum(int id) { |
| 83 | + /** |
| 84 | + * @brief Returns the sum of elements in range from 0 to ID. |
| 85 | + * @tparam T the type of the variables |
| 86 | + * @param id Index in original array up to which sum is evaluated. |
| 87 | + * @return Sum of elements in range from 0 to id. |
| 88 | + */ |
| 89 | + template <typename T> |
| 90 | + int sum(T id) { |
55 | 91 | id++;
|
56 |
| - int res = 0; |
| 92 | + T res = 0; |
57 | 93 | while (id > 0) {
|
58 | 94 | res += bit[id];
|
59 | 95 | id -= offset(id);
|
60 | 96 | }
|
61 | 97 | return res;
|
62 | 98 | }
|
63 | 99 |
|
64 |
| - /** Returns the prefix sum in range from l to r */ |
| 100 | + /** |
| 101 | + * @brief Returns the prefix sum in range from L to R. |
| 102 | + * @param l Left index of range. |
| 103 | + * @param r Right index of range. |
| 104 | + * @return Sum of elements in range from L to R. |
| 105 | + */ |
65 | 106 | int sum_range(int l, int r) { return sum(r) - sum(l - 1); }
|
66 | 107 | };
|
| 108 | +} // namespace range_queries |
67 | 109 |
|
68 |
| -/** Main function */ |
69 |
| -int main() { |
70 |
| - int n = 5; |
| 110 | +/** |
| 111 | + * @brief Self-test implementations |
| 112 | + * @returns void |
| 113 | + */ |
| 114 | +static void tests() { |
71 | 115 | std::vector<int> arr = {1, 2, 3, 4, 5};
|
72 |
| - FenwickTree fenwick_tree(arr); |
| 116 | + range_queries::fenwick_tree fenwick_tree(arr); |
73 | 117 |
|
74 | 118 | assert(fenwick_tree.sum_range(0, 0) == 1);
|
75 | 119 | assert(fenwick_tree.sum_range(0, 1) == 3);
|
76 | 120 | assert(fenwick_tree.sum_range(0, 2) == 6);
|
| 121 | + assert(fenwick_tree.sum_range(0, 3) == 10); |
| 122 | + assert(fenwick_tree.sum_range(0, 4) == 15); |
| 123 | + |
77 | 124 | fenwick_tree.update(0, 6);
|
78 |
| - assert(fenwick_tree.sum_range(0, 0) == 6); |
79 |
| - assert(fenwick_tree.sum_range(0, 1) == 8); |
80 |
| - assert(fenwick_tree.sum_range(0, 2) == 11); |
| 125 | + std::cout << "All tests have successfully passed!\n"; |
| 126 | +} |
| 127 | + |
| 128 | +/** |
| 129 | + * @brief Main function |
| 130 | + * @returns 0 on exit |
| 131 | + */ |
| 132 | +int main() { |
| 133 | + tests(); // run self-test implementations |
81 | 134 | return 0;
|
82 | 135 | }
|
0 commit comments