mirror of
https://hub.njuu.cf/TheAlgorithms/C-Plus-Plus.git
synced 2023-10-11 13:05:55 +08:00
Merge branch 'master' into kruskals_documentation
This commit is contained in:
commit
bd50a5219c
@ -1,48 +1,78 @@
|
|||||||
/**
|
/**
|
||||||
* @file
|
* @file
|
||||||
* @brief Fenwick tree
|
* @brief [Fenwick Tree](https://en.wikipedia.org/wiki/Fenwick_tree) algorithm
|
||||||
|
* implementation
|
||||||
|
* @details
|
||||||
|
* _From Wikipedia, the free encyclopedia._
|
||||||
*
|
*
|
||||||
* A Fenwick tree or binary indexed tree is a data structure
|
* A Fenwick tree or binary indexed tree (BIT) is a clever implementation of a
|
||||||
* that can efficiently update elements and calculate
|
* datastructure called bionomal tree. It can update values and solve range
|
||||||
* prefix sums in a table of numbers.
|
* queries with operations that is; commulative, associative and has an
|
||||||
|
* inverse for this type of element. It can also solve immutable range queries
|
||||||
|
* (min/max), when operations only are associative over this type of element.
|
||||||
|
* Some of these restrictions can be removed, by storing redunant information;
|
||||||
|
* like in max/min range queries.
|
||||||
|
*
|
||||||
|
* @author [Mateusz Grzegorzek](https://github.com/mateusz-grzegorzek)
|
||||||
|
* @author [David Leal](https://github.com/Panquesito7)
|
||||||
*/
|
*/
|
||||||
#include <cassert>
|
|
||||||
#include <iostream>
|
#include <cassert> /// for assert
|
||||||
#include <vector>
|
#include <iostream> /// for IO operations
|
||||||
|
#include <vector> /// for std::vector
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* n --> No. of elements present in input array.
|
* @namespace
|
||||||
* bit[0..n] --> Array that represents Binary Indexed Tree.
|
* @brief Range Queries
|
||||||
*/
|
*/
|
||||||
class FenwickTree {
|
namespace range_queries {
|
||||||
int n;
|
/**
|
||||||
std::vector<int> bit;
|
* @brief The class that initializes the Fenwick Tree.
|
||||||
|
*/
|
||||||
|
class fenwick_tree {
|
||||||
|
size_t n = 0; ///< No. of elements present in input array
|
||||||
|
std::vector<int> bit{}; ///< Array that represents Binary Indexed Tree.
|
||||||
|
|
||||||
/** Returns the highest power of two which is not more than x */
|
/**
|
||||||
|
* @brief Returns the highest power of two which is not more than `x`.
|
||||||
|
* @param x Index of element in original array.
|
||||||
|
* @return Offset of index.
|
||||||
|
*/
|
||||||
inline int offset(int x) { return (x & (-x)); }
|
inline int offset(int x) { return (x & (-x)); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** Constructor
|
/**
|
||||||
* \param[in] arr --> Input array for which prefix sum is evaluated.
|
* @brief Class Constructor
|
||||||
|
* @tparam T the type of the array
|
||||||
|
* @param[in] arr Input array for which prefix sum is evaluated.
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
explicit FenwickTree(const std::vector<int>& arr) {
|
template <typename T>
|
||||||
n = arr.size();
|
explicit fenwick_tree(const std::vector<T>& arr) : n(arr.size()) {
|
||||||
bit.assign(n + 1, 0);
|
bit.assign(n + 1, 0);
|
||||||
for (int i = 0; i < n; ++i) {
|
for (int i = 0; i < n; ++i) {
|
||||||
update(i, arr[i]);
|
update(i, arr[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Constructor
|
/**
|
||||||
* \param[in] x --> Size of array that represents Binary Indexed Tree.
|
* @brief Class Constructor
|
||||||
|
* @tparam T the type of the variable
|
||||||
|
* @param[in] x Size of array that represents Binary Indexed Tree.
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
explicit FenwickTree(int x) {
|
template <typename T>
|
||||||
n = x;
|
explicit fenwick_tree(T x) : n(x) { bit.assign(n + 1, 0); }
|
||||||
bit.assign(n + 1, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Add val at id */
|
/**
|
||||||
void update(int id, int val) {
|
* @brief Updates the value of an element in original array and
|
||||||
|
* accordingly updates the values in BIT array.
|
||||||
|
* @tparam T the type of the variables
|
||||||
|
* @param id Index of element in original array.
|
||||||
|
* @param val Value with which element's value is updated.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
void update(T id, T val) {
|
||||||
id++;
|
id++;
|
||||||
while (id <= n) {
|
while (id <= n) {
|
||||||
bit[id] += val;
|
bit[id] += val;
|
||||||
@ -50,10 +80,16 @@ class FenwickTree {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get prefix sum upto id */
|
/**
|
||||||
int sum(int id) {
|
* @brief Returns the sum of elements in range from 0 to ID.
|
||||||
|
* @tparam T the type of the variables
|
||||||
|
* @param id Index in original array up to which sum is evaluated.
|
||||||
|
* @return Sum of elements in range from 0 to id.
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
int sum(T id) {
|
||||||
id++;
|
id++;
|
||||||
int res = 0;
|
T res = 0;
|
||||||
while (id > 0) {
|
while (id > 0) {
|
||||||
res += bit[id];
|
res += bit[id];
|
||||||
id -= offset(id);
|
id -= offset(id);
|
||||||
@ -61,22 +97,39 @@ class FenwickTree {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the prefix sum in range from l to r */
|
/**
|
||||||
|
* @brief Returns the prefix sum in range from L to R.
|
||||||
|
* @param l Left index of range.
|
||||||
|
* @param r Right index of range.
|
||||||
|
* @return Sum of elements in range from L to R.
|
||||||
|
*/
|
||||||
int sum_range(int l, int r) { return sum(r) - sum(l - 1); }
|
int sum_range(int l, int r) { return sum(r) - sum(l - 1); }
|
||||||
};
|
};
|
||||||
|
} // namespace range_queries
|
||||||
|
|
||||||
/** Main function */
|
/**
|
||||||
int main() {
|
* @brief Self-test implementations
|
||||||
int n = 5;
|
* @returns void
|
||||||
|
*/
|
||||||
|
static void tests() {
|
||||||
std::vector<int> arr = {1, 2, 3, 4, 5};
|
std::vector<int> arr = {1, 2, 3, 4, 5};
|
||||||
FenwickTree fenwick_tree(arr);
|
range_queries::fenwick_tree fenwick_tree(arr);
|
||||||
|
|
||||||
assert(fenwick_tree.sum_range(0, 0) == 1);
|
assert(fenwick_tree.sum_range(0, 0) == 1);
|
||||||
assert(fenwick_tree.sum_range(0, 1) == 3);
|
assert(fenwick_tree.sum_range(0, 1) == 3);
|
||||||
assert(fenwick_tree.sum_range(0, 2) == 6);
|
assert(fenwick_tree.sum_range(0, 2) == 6);
|
||||||
|
assert(fenwick_tree.sum_range(0, 3) == 10);
|
||||||
|
assert(fenwick_tree.sum_range(0, 4) == 15);
|
||||||
|
|
||||||
fenwick_tree.update(0, 6);
|
fenwick_tree.update(0, 6);
|
||||||
assert(fenwick_tree.sum_range(0, 0) == 6);
|
std::cout << "All tests have successfully passed!\n";
|
||||||
assert(fenwick_tree.sum_range(0, 1) == 8);
|
}
|
||||||
assert(fenwick_tree.sum_range(0, 2) == 11);
|
|
||||||
|
/**
|
||||||
|
* @brief Main function
|
||||||
|
* @returns 0 on exit
|
||||||
|
*/
|
||||||
|
int main() {
|
||||||
|
tests(); // run self-test implementations
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user