-
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.
C++20 update on CMake | Added bubble class | new test cases
Now bubble class is on it's first step, we have to make more of it though in the future as i explain in some comments(this could be a paper). I fixed some issues with the avl class and added test cases for the new container
- Loading branch information
1 parent
e90f481
commit 4097918
Showing
8 changed files
with
326 additions
and
13 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
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 |
---|---|---|
|
@@ -3,3 +3,11 @@ If: | |
|
||
CompileFlags: | ||
Add: [-std=c++20] | ||
|
||
--- | ||
|
||
If: | ||
PathMatch: .*\.h | ||
|
||
CompileFlags: | ||
Add: [-std=c++20] |
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,13 @@ | ||
If: | ||
PathMatch: .*\.cc | ||
|
||
CompileFlags: | ||
Add: [-std=c++23] | ||
|
||
--- | ||
|
||
If: | ||
PathMatch: .*\.h | ||
|
||
CompileFlags: | ||
Add: [-std=c++23] |
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,209 @@ | ||
/** | ||
* This is the bubble data structure, we highly suggest to initialize it with a various range of elements | ||
* like {-500, -100, 0, 100, 500}(for _SIZE=5) if you want to use elements from [-500, 500]. In the future, we will | ||
* work on making it more generic and make the list change, for example, if the user give {-2, -1, 0, 1, 2} and always | ||
* insert keys with value > 2, then bubble will not work efficiently, so this has to change in the future | ||
*/ | ||
|
||
#ifndef BUBBLE_H | ||
#define BUBBLE_H | ||
|
||
#ifdef __cplusplus | ||
#include <iostream> | ||
#include <print> | ||
#include <vector> | ||
#include <optional> | ||
#include <ranges> | ||
#include <algorithm> | ||
#include <utility> | ||
#include <cassert> | ||
#include "../../classes/tree/avl_tree.h" | ||
#endif | ||
|
||
template <typename T, size_t _SIZE> | ||
class bubble { | ||
private: | ||
std::vector<std::pair<T, std::optional<avl_tree<T>>>> list; | ||
size_t _size; | ||
|
||
public: | ||
explicit bubble() noexcept : _size(0) { } | ||
|
||
template <size_t _NEW_SIZE> | ||
bubble(const bubble<T, _NEW_SIZE> &t) noexcept : _size(t._size) { | ||
try { | ||
if(_NEW_SIZE != _SIZE) { throw std::logic_error("Tried to copy bubbles with different sizes"); } | ||
this->list = t.list; | ||
} | ||
catch (std::logic_error &e){ | ||
std::cerr << e.what() << '\n'; | ||
} | ||
} | ||
|
||
template <typename... Args> | ||
void insert(Args&& ...keys); | ||
|
||
template <typename... Args> | ||
void remove(Args&& ...keys); | ||
|
||
bool search(const T& key); | ||
|
||
size_t size(); | ||
|
||
bool empty(); | ||
|
||
std::vector<T> operator[] (const size_t& index) const { | ||
assert(index < this->_size && index >= 0); | ||
if(this->list[index].second == std::nullopt) { return {this->list[index].first}; } | ||
return this->list[index].second.value().inorder(); | ||
} | ||
|
||
friend std::ostream & operator << (std::ostream &out, const bubble<T, _SIZE> &t){ | ||
if(t._size == 0) { return out; } | ||
for(auto && x : t.list) { | ||
out << x.first << ": {"; | ||
if(x.second == std::nullopt){ | ||
out << "}" << '\n'; | ||
continue; | ||
} | ||
avl_tree<T> tmp_tree(x.second.value()); | ||
std::vector<T> ino = tmp_tree.inorder(); | ||
for(size_t i = 0; i<ino.size(); i++){ | ||
if(i == ino.size() - 1) { | ||
out << ino[i]; | ||
} | ||
else{ | ||
out << ino[i] << " "; | ||
} | ||
} | ||
out << "}" << '\n'; | ||
} | ||
return out; | ||
} | ||
}; | ||
|
||
template <typename T, size_t _SIZE> | ||
template <typename... Args> | ||
inline void bubble<T, _SIZE>::insert(Args&& ...keys) { | ||
auto _insert = [&](const T&& key) -> void { | ||
if(_size < _SIZE) { | ||
list.push_back({key, std::nullopt}); | ||
_size++; | ||
return; | ||
} | ||
if(_size == _SIZE) { | ||
std::ranges::sort(list, [](const std::pair<T, std::optional<avl_tree<T>>> &a, const std::pair<T, std::optional<avl_tree<T>>> &b){ | ||
return a.first < b.first; | ||
}); | ||
} | ||
|
||
auto it = std::lower_bound(std::ranges::begin(this->list), std::ranges::end(this->list), key, [](const std::pair<T, std::optional<avl_tree<T>>> &pair, const T &key){ return pair.first < key; }); | ||
|
||
if(it != std::ranges::end(this->list)) { | ||
int idx = std::distance(std::ranges::begin(this->list), it); | ||
if(idx - 1 < 0){ | ||
if(this->list[0].second == std::nullopt) { | ||
this->list[0].second = avl_tree<T>(); | ||
} | ||
this->list[0].second.value().insert(key); | ||
} | ||
else{ | ||
if(this->list[idx - 1].second == std::nullopt) { | ||
this->list[idx - 1].second = avl_tree<T>(); | ||
} | ||
this->list[idx - 1].second.value().insert(key); | ||
} | ||
} | ||
else { | ||
if(this->list[this->list.size() - 1].second == std::nullopt){ | ||
this->list[this->list.size() - 1].second = avl_tree<T>(); | ||
} | ||
this->list[this->list.size() - 1].second.value().insert(key); | ||
} | ||
_size++; | ||
}; | ||
(std::invoke(_insert, std::forward<Args>(keys)), ...); | ||
} | ||
|
||
|
||
/** | ||
* For now remove function can't remove key elements that exist on the list | ||
* It can only remove them if none of the nodes have a tree yet. | ||
* We have to find a way to make the tree rebalance itself and the root of the tree come on top | ||
* after a removal of a key element | ||
*/ | ||
template <typename T, size_t _SIZE> | ||
template <typename... Args> | ||
void bubble<T, _SIZE>::remove(Args&& ...keys) { | ||
auto _remove = [&](const T& key) -> void{ | ||
if(this->_size == 0) { return; } | ||
if(this->_size <= _SIZE) { | ||
auto [begin, end] = std::ranges::remove_if(this->list, [&](const std::pair<T, std::optional<avl_tree<T>>> &t) { return t.first == key; }); | ||
list.erase(begin, end); | ||
_size--; | ||
} | ||
else{ | ||
auto it = std::lower_bound(std::ranges::begin(this->list), std::ranges::end(this->list), key, [](const std::pair<T, std::optional<avl_tree<T>>> &pair, const T &key){ return pair.first < key; }); | ||
if(it != std::ranges::end(this->list)) { | ||
size_t idx = std::ranges::distance(std::ranges::begin(this->list), it); | ||
if(idx - 1 < 0){ | ||
if(this->list[0].second == std::nullopt){ | ||
return; | ||
} | ||
this->list[0].second.value().remove(key); | ||
} | ||
else{ | ||
if(this->list[idx - 1].second == std::nullopt) { | ||
return; | ||
} | ||
this->list[idx - 1].second.value().remove(key); | ||
} | ||
} | ||
else { | ||
if(this->list[this->list.size() - 1].second == std::nullopt) { | ||
return; | ||
} | ||
this->list[this->list.size() - 1].second.value().remove(key); | ||
} | ||
_size--; | ||
} | ||
}; | ||
(std::invoke(_remove, std::forward<Args>(keys)), ...); | ||
} | ||
|
||
template <typename T, size_t _SIZE> | ||
bool bubble<T, _SIZE>::search(const T& key) { | ||
if(this->_size == 0) { return false; } | ||
auto it = std::lower_bound(std::ranges::begin(this->list), std::ranges::end(this->list), key, [](const std::pair<T, std::optional<avl_tree<T>>> &pair, const T &key){ return pair.first < key; }); | ||
if (it != std::ranges::end(this->list)){ | ||
size_t idx = std::ranges::distance(std::ranges::begin(this->list), it); | ||
if(idx - 1 < 0){ | ||
if(this->list[0].first == key) { return true; } | ||
if(this->list[0].second == std::nullopt) { return false; } | ||
if(this->list[0].second.value().search(key) == true) { return true; } | ||
} | ||
else { | ||
if(this->list[idx].first == key) { return true; } | ||
if(this->list[idx - 1].second == std::nullopt) { return false; } | ||
if(this->list[idx - 1].second.value().search(key) == true) { return true; } | ||
} | ||
} | ||
else { | ||
if(this->list[this->list.size() - 1].first == key) { return true; } | ||
if(this->list[this->list.size() - 1].second == std::nullopt) { return false; } | ||
if(this->list[this->list.size() - 1].second.value().search(key) == true) { return true; } | ||
} | ||
return false; | ||
} | ||
|
||
template <typename T, size_t _SIZE> | ||
size_t bubble<T, _SIZE>::size() { | ||
return this->_size; | ||
} | ||
|
||
template <typename T, size_t _SIZE> | ||
bool bubble<T, _SIZE>::empty() { | ||
return this->_size == 0; | ||
} | ||
|
||
#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
Oops, something went wrong.