mirror of
https://hub.njuu.cf/TheAlgorithms/C-Plus-Plus.git
synced 2023-10-11 13:05:55 +08:00
feat: Segment Tree Data Structure (#2444)
* Segment Tree * fix: conformed to guidelines * fix: changed int to template type T in few places * fix: suggested changes Co-authored-by: David Leal <halfpacho@gmail.com> * fix: suggested changes Co-authored-by: David Leal <halfpacho@gmail.com> * fixed: suggested changes Co-authored-by: David Leal <halfpacho@gmail.com> * fix: suggested changes Co-authored-by: David Leal <halfpacho@gmail.com> * fix: suggested changes Co-authored-by: David Leal <halfpacho@gmail.com> * fix: suggested changes Co-authored-by: David Leal <halfpacho@gmail.com> * fix: suggested changes Co-authored-by: David Leal <halfpacho@gmail.com> * fix: suggested changes Co-authored-by: David Leal <halfpacho@gmail.com> * fix: suggested changes Co-authored-by: David Leal <halfpacho@gmail.com> * fix: remove duplicate line * Update segment_tree.cpp * chore: apply suggestions from code review --------- Co-authored-by: David Leal <halfpacho@gmail.com>
This commit is contained in:
parent
c0c27153cd
commit
1a1570d775
133
data_structures/segment_tree.cpp
Executable file
133
data_structures/segment_tree.cpp
Executable file
@ -0,0 +1,133 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief A data structure to quickly do operations on ranges: the [Segment Tree](https://en.wikipedia.org/wiki/Segment_tree) algorithm implementation
|
||||
* @details
|
||||
* Implementation of the segment tree data structre
|
||||
*
|
||||
* Can do point updates (updates the value of some position)
|
||||
* and range queries, where it gives the value of some associative
|
||||
* opperation done on a range
|
||||
*
|
||||
* Both of these operations take O(log N) time
|
||||
* @author [Nishant Chatterjee](https://github.com/nishantc1527)
|
||||
*/
|
||||
|
||||
#include <iostream> /// For IO operations
|
||||
#include <vector> /// For std::vector
|
||||
#include <algorithm> /// For std::min and std::max
|
||||
#include <cassert> /// For assert
|
||||
|
||||
/*
|
||||
* @namespace
|
||||
* @brief Data structures
|
||||
*/
|
||||
namespace data_structures {
|
||||
/**
|
||||
* @brief class representation of the segment tree
|
||||
* @tparam T The type of the class that goes in the datastructure
|
||||
*/
|
||||
template <class T>
|
||||
class SegmentTree {
|
||||
private:
|
||||
const T ID = 0; ///< Comb(ID, x) = x
|
||||
std::vector<T> t; ///< Vector to represent the tree
|
||||
int size = 0; ///< Number of elements available for querying in the tree
|
||||
private:
|
||||
/**
|
||||
* @brief Any associative function that combines x and y
|
||||
* @param x The first operand
|
||||
* @param y The second operand
|
||||
* @return Some associative operation applied to these two values. In this case, I used addition
|
||||
*/
|
||||
T comb(T x, T y) {
|
||||
return x + y;
|
||||
}
|
||||
/**
|
||||
* @brief Gives the midpoint between two integers
|
||||
* @param l The left endpoint
|
||||
* @param r The right endpoint
|
||||
* @return the middle point between them
|
||||
*/
|
||||
int mid(int l, int r) {
|
||||
return l + (r - l) / 2;
|
||||
}
|
||||
/**
|
||||
* @brief Helper method for update method below
|
||||
* @param i The index of the current node
|
||||
* @param l The leftmost node of the current node
|
||||
* @param r The rightmost node of the current node
|
||||
* @param pos The position to update
|
||||
* @param val The value to update it to
|
||||
*/
|
||||
void update(int i, int l, int r, int pos, T val) {
|
||||
if(l == r) t[i] = val;
|
||||
else {
|
||||
int m = mid(l, r);
|
||||
if(pos <= m) update(i * 2, l, m, pos, val);
|
||||
else update(i * 2 + 1, m + 1, r, pos, val);
|
||||
t[i] = comb(t[i * 2], t[i * 2 + 1]);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief Helper method for range_comb method below
|
||||
* @param i The current node
|
||||
* @param l The leftmost node of the current node
|
||||
* @param r The rightmost node of the current node
|
||||
* @param tl The left endpoint of the range
|
||||
* @param tr The right endpoint of the range
|
||||
* @return The comb operation applied to all values between tl and tr
|
||||
*/
|
||||
T range_comb(int i, int l, int r, int tl, int tr) {
|
||||
if(l == tl && r == tr) return t[i];
|
||||
if(tl > tr) return 0;
|
||||
int m = mid(l, r);
|
||||
return comb(range_comb(i * 2, l, m, tl, std::min(tr, m)), range_comb(i * 2 + 1, m + 1, r, std::max(tl, m + 1), tr));
|
||||
}
|
||||
public:
|
||||
SegmentTree(int n) : t(n * 4, ID), size(n) {}
|
||||
/**
|
||||
* @brief Updates a value at a certain position
|
||||
* @param pos The position to update
|
||||
* @param val The value to update it to
|
||||
*/
|
||||
void update(int pos, T val) {
|
||||
update(1, 1, size, pos, val);
|
||||
}
|
||||
/**
|
||||
* @brief Returns comb across all values between l and r
|
||||
* @param l The left endpoint of the range
|
||||
* @param r The right endpoint of the range
|
||||
* @return The value of the comb operations
|
||||
*/
|
||||
T range_comb(int l, int r) {
|
||||
return range_comb(1, 1, size, l, r);
|
||||
}
|
||||
};
|
||||
} // namespace data_structures
|
||||
|
||||
/**
|
||||
* @brief Self-test implementations
|
||||
* @returns void
|
||||
*/
|
||||
static void test() {
|
||||
data_structures::SegmentTree<int> t(5);
|
||||
t.update(1, 1);
|
||||
t.update(2, 2);
|
||||
t.update(3, 3);
|
||||
t.update(4, 4);
|
||||
t.update(5, 5);
|
||||
assert(t.range_comb(1, 3) == 6); // 1 + 2 + 3 = 6
|
||||
t.update(1, 3);
|
||||
assert(t.range_comb(1, 3) == 8); // 3 + 2 + 3 = 8
|
||||
|
||||
std::cout << "All tests have successfully passed!\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Main function
|
||||
* @returns 0 on exit
|
||||
*/
|
||||
int main() {
|
||||
test(); // run self-test implementations
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user