- Red and black tree
- map, dictionary
- set, ordered set
- multiset, a multiset
I have implemented one of the types of self-balancing binary search trees - red-black дерево
Standard library containers were also implemented - map set multiset
The code style in the project is Google code style c++
the namespace is used throughout the project jokerooo7 namespace jokerooo7
The red-black tree is implemented in the form of the RBTree class, which can be represented as a single template parameter:
#include "red_black_tree.h"
int main() {
jokerooo7::RBTree<int> my_class_one;
jokerooo7::RBTree<std::pair<int, bool>> my_class_two;
}
My implementation does not use allocators and comparators:
template <typename K>
class RBtree {...}
The red-black tree is represented as files red_black_tree.h
red_black_tree.top
According to the rule of five c++, I have implemented all the basic constructs. Additionally, a constructor is implemented with the transfer of data to the tree in the format std::initializer_list<value_type>
RBTree() = default;
RBTree(std::initializer_list<value_type> const& items);
RBTree(const RBTree& other);
RBTree(RBTree&& other) noexcept;
~RBTree();
RBTree& operator=(const RBTree& other);
RBTree& operator=(RBTree&& other);
As in the standard library, I have two methods implemented - begin() and end().
begin()
- returns an iterator that points to the initial branch of the tree (the smallest).
end()
- returns an iterator that points to an empty leaf following the largest element(null ptr), if necessary, you can return to the largest element.
iterator begin() const;
iterator end() const;
// return immutable iterators
const_iterator cbegin() const;
const_iterator cend() const;
typename jokerooo7::multiset<K>::iterator iter_one = my_class_one.begin();
++iter_one; // returns the next node, the value above it
typename jokerooo7::multiset<K>::iterator iter_two = my_class_one.end();
--iter_two; // returns the largest element
Implemented the size()
and max_size()
methods
size()
- returns the number of elements in the tree
max_size()
- uses the std::allocator<value_type>
class to determine the maximum size of the container
insert_many()
is a method that takes a large number of arguments and inserts into a container and returns a vector with a pair of iterators and a conditional(bool) value, whether the element was inserted or not.
Uses the protected method inside itself InsertInTree()
to insert elements
In order for two containers to swap elements, the swap(RB Tree & other)
method is used, which takes another class as a way to replace two elements.
merge(RBTree& other)
- Is used to accept all its elements from another container, without removing elements from another.
To delete an element, the erase(iterator any)
method is used, which accepts an iterator to be deleted from the container.
The clear()
method is used to clear the entire container
The InsertInTree*()
method is used, as arguments to the function it takes a value of the current type in the container, and a pair of flags (std::pair<bool, bool> mode
). mode.first
- Whether it is necessary to rewrite existing elements, mode second
- whether it is possible to add identical elements in the container.
It returns a pair, an iterator for the inserted element and its conditional(bool) value, whether the element was inserted or not.
Implemented a method named Content()
to check whether the current element exists in the container or not.
It takes a value and searches for it in the container. Using the private methods IsItMore() IsItLess() AreTheyEqual()
compares as simple elements, so it can compare the data type std::pait<anyType, anyType>.
An auxiliary method has been implemented to check whether the two current containers match each other.
bool EqualityOfClasses(const RBTree& other)
are used to self-balance the tree in cases of deleting, inserting, and checking tree nodes. The algorithm was used from wiki
RB Tree contains two internal classes, TreeIterator and Tree Const Iterator.
To make their call in derived classes conform to the standard library, I use the aliases iterator
and const_iterator
Iterators, as in the standard library, are not protected from accessing a remote node. You need to monitor this yourself.
int main() {
jokerooo7::RBTree<int> my_class_one;
typename jokerooo7::multiset<K>::iterator iter_one = my_class_one.begin();
}
The iterator class has operators implemented *, =, ++, --, !=, ==
typename jokerooo7::multiset<K>::iterator iter_one = my_class_one.begin()
*iter_one; // Returns the value that lies in this iterator
++iter_one; // Will move to the next element and fix the iterator on this node and return it
to eater_one++; // Will return a copy of the current iterator, move to the next one and fix it
to eater_one != any_iterator; // Returns a null value - they do not match or not
iter_one == any_iterator; // The opposite!=
iter_one = any_iterator_or_node; // Assign to the current iterator - another iterator or node of the tree, also works with std::move
##include <stddef> // To work with the size_t data type
#include <utility> // To work with std::pair
##include <vector> // To return a vector with multiple inserts
#include <initializer_list> // To insert a large number of arguments
The file with the rating is "map.h"
My class, as well as the colorfully black tree class, is hosted in the im jokerooo7 application and uses two templates arguments - key and value <type name KT, type name T>
#include "red_black_tree.h"
namespace jokerooo7 {
template <typename KT, typename T>
class map : public RBTree<std::pair<KT, T> {...}
}
My implementation of the STL library map uses the already written red-black tree. It inherits all the methods and uses the construction using Btree<std::pair<KT, T>>::RB Tree;
inherits absolutely all constructors and dextrators of the red-black tree class.
Aliases match the standard library and can be seen in the "map.h" files
std::pair<iterator, bool> insert(const value_type& value) {
return this->InsertInTree(value, std::make_pair(false, false));
};
std::pair<iterator, bool> insert(const Key& key, const T& obj) {
value_type value = std::make_pair(key, obj);
return this->InsertInTree(value, std::make_pair(false, false));
};
std::pair<iterator, bool> insert_or_assign(const Key& key, const T& obj) {
value_type value = std::make_pair(key, obj);
return this->InsertInTree(value, std::make_pair(true, false));
};
These three constructs use InsertInTree from RBTree to insert elements and return the same as InsertInTree()
- The first method inserts only the value, without the key
- The second method inserts key-values, without rewriting the value
- The third method is inserting with rewriting the values by key
The contains()
method implements a check for the presence of a key in the container and returns a conditional(bool) value about its presence or absence
The contains()
function uses Content() to check the contents.
The at()
method implements the return of a non-constant reference/or constant value by key, if the key is not found, throws an exception. Uses Content()
The []
operator Returns an element by key and allows you to insert an element by key. Uses at()
The file with the implementation is "set.h"
My class, as well as the red-black tree class, is located in the jokerooo7 namespace and takes one template argument - the value template <typename T>
My implementation of the STL library set uses the already written red-black tree. It inherits all methods and, using the using RBTree<KT>::RBTree;
construct, inherits absolutely all constructors and dextrators of the red-black tree class.
Aliases match the standard library and can be seen in the "set.h" files
std::pair<iterator, bool> insert(const value_type& value) {
return this->InsertInTree(value, std::make_pair(false, false));
};
Inserting the value element uses InsertInTree from RBTree, to insert elements and return the same as InsertInTree()
contains()
- the same as for map, takes the value that is the key in set
the find()
function returns an iterator to an element that uses Content() to check the contents.
The same as set, but allows you to store duplicate elements.
The file with the implementation is "multiset.h"
Many RBTree methods have been rewritten, supplemented and the implementation has been changed, due to the addition of the same content
The methods are the same as multiset, supplemented by some:
iterator lower_bound(const Key& key)
- the method finds the first element at least the specified oneiterator upper_bound(const Key& key)
- method that finds more than the specified valuesize_type count(const Key& key) const
- returns the number of key data in the containerstd::pair<iterator, iterator> equal_range(const Key& key)
- returns a pair of iterators, where the first one points to the first matching key, and the second one to the next (larger in value) after the given key;