-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1df011f
commit b1048f4
Showing
6 changed files
with
356 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
#ifdef __cplusplus | ||
#include "../../src/classes/tree/interval_tree.h" | ||
#include <iostream> | ||
#endif | ||
|
||
int main() { | ||
interval_tree<int> i; | ||
i.insert({20, 36}); | ||
i.insert({3, 41}); | ||
i.insert({29, 99}); | ||
i.insert({0, 1}); | ||
i.insert({10, 15}); | ||
|
||
// you can visualize the tree | ||
i.visualize(); | ||
|
||
// you can get the elements in any order | ||
std::vector<std::pair<int, int>> __preorder = i.preorder(); | ||
std::vector<std::pair<int, int>> __inorder = i.inorder(); | ||
// .... | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,6 @@ | ||
digraph Tree { | ||
a->t | ||
t->f | ||
f->p | ||
p->o | ||
o->m | ||
t->w | ||
"20,36"->"3,41" | ||
"3,41"->"0,1" | ||
"3,41"->"10,15" | ||
"20,36"->"29,99" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,294 @@ | ||
#ifndef INTERVAL_TREE_H | ||
#define INTERVAL_TREE_H | ||
|
||
#include <memory> | ||
#ifdef __cplusplus | ||
#include "../../visualization/tree_visual/tree_visualization.h" | ||
#include <iostream> | ||
#endif | ||
|
||
/* | ||
*interval tree class | ||
*/ | ||
template <typename T> class interval_tree { | ||
public: | ||
interval_tree(std::vector<std::pair<T, T>> v = {}) { | ||
if (!v.empty()) { | ||
for (auto &x : v) { | ||
this->insert({x.first, x.second}); | ||
} | ||
} | ||
} | ||
|
||
/* | ||
*insert function. | ||
8@param p: interval to be inserted. | ||
*/ | ||
void insert(std::pair<T, T> p) { | ||
interval i = interval(p); | ||
root = __insert(root, i); | ||
} | ||
|
||
/* | ||
*remove function. | ||
*@param p: interval to be removed. | ||
*/ | ||
void remove(std::pair<T, T> p) { | ||
interval i = interval(p); | ||
root = __remove(root, i); | ||
} | ||
|
||
/* | ||
*overlap function. | ||
*@param p1: first interval. | ||
*@param p2: second interval. | ||
*Returns true if p1 overlaps p2. | ||
*/ | ||
bool overlap(std::pair<T, T> p1, std::pair<T, T> p2) { | ||
interval i1 = interval(p1), i2 = interval(p2); | ||
return i1.high >= i2.low && i1.low <= i2.high; | ||
} | ||
|
||
/* | ||
*inorder function. | ||
*Returns vector<pair<T,T>>, the elements inorder. | ||
*/ | ||
std::vector<std::pair<T, T>> inorder() { | ||
std::vector<std::pair<T, T>> path; | ||
__inorder( | ||
[&](std::shared_ptr<node> callbacked) { | ||
path.push_back({callbacked->i->low, callbacked->i->high}); | ||
}, | ||
root); | ||
return path; | ||
} | ||
|
||
/* | ||
*preorder function. | ||
*Returns vector<pair<T,T>>, the elements preorder. | ||
*/ | ||
std::vector<std::pair<T, T>> preorder() { | ||
std::vector<std::pair<T, T>> path; | ||
__preorder( | ||
[&](std::shared_ptr<node> callbacked) { | ||
path.push_back({callbacked->i->low, callbacked->i->high}); | ||
}, | ||
root); | ||
return path; | ||
} | ||
|
||
/* | ||
*postorder function. | ||
*Returns vector<pair<T, T>>, the elements postorder. | ||
*/ | ||
std::vector<std::pair<T, T>> postorder() { | ||
std::vector<std::pair<T, T>> path; | ||
__postorder( | ||
[&](std::shared_ptr<node> callbacked) { | ||
path.push_back({callbacked->i->low, callbacked->i->high}); | ||
}, | ||
root); | ||
return path; | ||
} | ||
|
||
void visualize() { | ||
std::string __generated = generate_visualization(); | ||
visualization::visualize(__generated); | ||
} | ||
|
||
/* | ||
*<< operator for interval_tree class. | ||
*/ | ||
friend std::ostream &operator<<(std::ostream &out, interval_tree<T> &t) { | ||
if (!t.root) { | ||
out << ""; | ||
return out; | ||
} | ||
out << '"'; | ||
std::vector<std::pair<T, T>> __inorder = t.inorder(); | ||
for (auto &x : __inorder) { | ||
out << '"' << x.first << ' ' << x.second << '"' << " "; | ||
} | ||
out << '"'; | ||
return out; | ||
} | ||
|
||
private: | ||
struct interval { | ||
T low; | ||
T high; | ||
interval(std::pair<T, T> p) | ||
: low(std::min(p.first, p.second)), high(std::max(p.first, p.second)) {} | ||
}; | ||
struct node { | ||
interval *i; | ||
int max; | ||
std::shared_ptr<node> right; | ||
std::shared_ptr<node> left; | ||
node(interval n) | ||
: i(new interval(n)), max(n.high), right(nullptr), left(nullptr) {} | ||
}; | ||
std::shared_ptr<node> root; | ||
|
||
std::shared_ptr<node> new_node(interval i) { | ||
std::shared_ptr<node> p = std::make_shared<node>(i); | ||
return p; | ||
} | ||
|
||
/* | ||
*helper function for insertion | ||
*/ | ||
std::shared_ptr<node> __insert(std::shared_ptr<node> root, interval i) { | ||
if (!root) { | ||
return new_node(i); | ||
} | ||
T l = root->i->low; | ||
if (i.low < l) { | ||
root->left = __insert(root->left, i); | ||
} else { | ||
root->right = __insert(root->right, i); | ||
} | ||
if (root->max < i.high) { | ||
root->max = i.high; | ||
} | ||
return root; | ||
} | ||
|
||
/* | ||
*helper function for remove. | ||
*/ | ||
std::shared_ptr<node> __remove(std::shared_ptr<node> root, interval i) { | ||
if (!root) { | ||
return nullptr; | ||
} | ||
std::shared_ptr<node> p = root; | ||
while (p) { | ||
if (p->i->low > i.low) { | ||
p = p->left; | ||
} else if (p->i->low < i.low) { | ||
p = p->right; | ||
} else { | ||
if (!p->right && !p->left) { | ||
return nullptr; | ||
} else if (p->right && !p->left) { | ||
std::shared_ptr<node> temp = root->right; | ||
return temp; | ||
} else if (p->left && !p->right) { | ||
std::shared_ptr<node> temp = p->left; | ||
return temp; | ||
} else { | ||
std::shared_ptr<node> temp = root; | ||
while (temp && temp->left) { | ||
temp = temp->left; | ||
} | ||
p->i = temp->i; | ||
p->max = temp->max; | ||
p->right = __remove(p->right, *temp->i); | ||
} | ||
} | ||
} | ||
return root; | ||
} | ||
|
||
void __inorder(std::function<void(std::shared_ptr<node>)> callback, | ||
std::shared_ptr<node> root) { | ||
if (root) { | ||
__inorder(callback, root->left); | ||
callback(root); | ||
__inorder(callback, root->right); | ||
} | ||
} | ||
|
||
void __postorder(std::function<void(std::shared_ptr<node>)> callback, | ||
std::shared_ptr<node> root) { | ||
if (root) { | ||
__postorder(callback, root->left); | ||
__postorder(callback, root->right); | ||
callback(root); | ||
} | ||
} | ||
|
||
void __preorder(std::function<void(std::shared_ptr<node>)> callback, | ||
std::shared_ptr<node> root) { | ||
if (root) { | ||
callback(root); | ||
__preorder(callback, root->left); | ||
__preorder(callback, root->right); | ||
} | ||
} | ||
|
||
std::string generate_visualization() { | ||
std::string __generate = __inorder_gen(root); | ||
return __generate; | ||
} | ||
|
||
std::string __inorder_gen(std::shared_ptr<node> root) { | ||
std::string __s; | ||
if (std::is_same_v<T, char> || std::is_same_v<T, std::string>) { | ||
if (root->left) { | ||
__s += '"'; | ||
__s += root->i->low; | ||
__s += ','; | ||
__s += root->i->high; | ||
__s += '"'; | ||
__s += "->"; | ||
__s += '"'; | ||
__s += root->left->i->low; | ||
__s += ','; | ||
__s += root->left->i->high; | ||
__s += '"'; | ||
__s += "\n"; | ||
__s += __inorder_gen(root->left); | ||
} | ||
if (root->right) { | ||
__s += '"'; | ||
__s += root->i->low; | ||
__s += ','; | ||
__s += root->i->high; | ||
__s += '"'; | ||
__s += "->"; | ||
__s += '"'; | ||
__s += root->right->i->low; | ||
__s += ','; | ||
__s += root->right->i->high; | ||
__s += '"'; | ||
__s += "\n"; | ||
__s += __inorder_gen(root->right); | ||
} | ||
} else { | ||
if (root->left) { | ||
__s += '"'; | ||
__s += std::to_string(root->i->low); | ||
__s += ','; | ||
__s += std::to_string(root->i->high); | ||
__s += '"'; | ||
__s += "->"; | ||
__s += '"'; | ||
__s += std::to_string(root->left->i->low); | ||
__s += ','; | ||
__s += std::to_string(root->left->i->high); | ||
__s += '"'; | ||
__s += "\n"; | ||
__s += __inorder_gen(root->left); | ||
} | ||
if (root->right) { | ||
__s += '"'; | ||
__s += std::to_string(root->i->low); | ||
__s += ','; | ||
__s += std::to_string(root->i->high); | ||
__s += '"'; | ||
__s += "->"; | ||
__s += '"'; | ||
__s += std::to_string(root->right->i->low); | ||
__s += ','; | ||
__s += std::to_string(root->right->i->high); | ||
__s += '"'; | ||
__s += "\n"; | ||
__s += __inorder_gen(root->right); | ||
} | ||
} | ||
return __s; | ||
} | ||
}; | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
#define CATCH_CONFIG_MAIN | ||
#include "../../src/classes/tree/interval_tree.h" | ||
#include "../catch2/catch.hpp" | ||
#include <string> | ||
|
||
TEST_CASE("testing insertion") { | ||
interval_tree<int> i; | ||
i.insert({20, 36}); | ||
i.insert({3, 41}); | ||
i.insert({29, 99}); | ||
i.insert({0, 1}); | ||
i.insert({10, 15}); | ||
std::vector<std::pair<int, int>> els = { | ||
{0, 1}, {3, 41}, {10, 15}, {20, 36}, {29, 99}}; | ||
REQUIRE(i.inorder() == els); | ||
} | ||
|
||
TEST_CASE("testing overlap") { | ||
interval_tree<int> i; | ||
i.insert({20, 36}); | ||
i.insert({3, 41}); | ||
i.insert({29, 99}); | ||
i.insert({0, 1}); | ||
i.insert({10, 15}); | ||
REQUIRE(i.overlap({20, 36}, {3, 41}) == true); | ||
REQUIRE(i.overlap({20, 36}, {10, 15}) == false); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
digraph Tree { | ||
"20,36"->"3,41" | ||
"3,41"->"0,1" | ||
"3,41"->"10,15" | ||
"20,36"->"29,99" | ||
} |