31 #ifndef ETL_MULTISET_INCLUDED
32 #define ETL_MULTISET_INCLUDED
51 #if ETL_CPP11_SUPPORTED && ETL_NOT_USING_STLPORT && ETL_USING_STL
52 #include <initializer_list>
75 multiset_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
89 multiset_full(string_type file_name_, numeric_type line_number_)
213 parent = ETL_NULLPTR;
214 children[0] = ETL_NULLPTR;
215 children[1] = ETL_NULLPTR;
220 uint_least8_t weight;
250 node.parent = parent;
267 Node* detached = position;
275 replacement =
swap->children[1 -
swap->dir];
277 if (replacement != ETL_NULLPTR)
279 replacement->parent =
swap->parent;
283 swap->parent = detached->parent;
284 swap->children[kLeft] = detached->children[kLeft];
285 swap->children[kRight] = detached->children[kRight];
286 if (
swap->children[kLeft])
288 swap->children[kLeft]->parent =
swap;
290 if (
swap->children[kRight])
292 swap->children[kRight]->parent =
swap;
294 swap->weight = detached->weight;
305 Node* weight_node = critical_node->children[critical_node->dir];
309 if (kNeither != weight_node->dir)
312 if (weight_node->weight == 1 - weight_node->dir)
314 weight_node->weight = kNeither;
318 weight_node->weight = weight_node->dir;
322 weight_node = weight_node->children[weight_node->dir];
332 if (kNeither == critical_node->weight)
334 critical_node->weight = critical_node->dir;
337 else if (critical_node->dir != critical_node->weight)
339 critical_node->weight = kNeither;
346 if (critical_node->weight == critical_node->children[critical_node->dir]->dir)
355 critical_node->children[critical_node->dir]->children[1 - critical_node->dir]->dir);
367 Node* limit_node = position;
368 while (limit_node && limit_node->children[dir])
370 limit_node = limit_node->children[dir];
385 if (position->children[kRight])
394 Node* parent = position;
399 parent = position->parent;
401 }
while (parent && parent->children[kRight] == position);
417 if (position->children[kRight])
426 const Node* parent = position;
431 parent = position->parent;
433 }
while (parent && parent->children[kRight] == position);
455 if (position->children[kLeft])
464 Node* parent = position;
469 parent = position->parent;
471 }
while (parent && parent->children[kLeft] == position);
493 if (position->children[kLeft])
502 const Node* parent = position;
507 parent = position->parent;
509 }
while (parent && parent->children[kLeft] == position);
534 Node* new_root = position->children[dir];
537 position->children[dir] = new_root->children[1 - dir];
539 if (position->children[dir])
541 position->children[dir]->parent = position;
545 new_root->parent = position->parent;
546 new_root->children[1 - dir] = position;
547 new_root->dir = 1 - dir;
550 position->weight = kNeither;
552 position->parent = new_root;
555 position->weight = kNeither;
576 Node* new_root = position->children[dir]->children[1 - dir];
578 position->children[dir]->weight = third != kNeither && third != dir ? dir : uint_least8_t(kNeither);
581 position->children[dir]->children[1 - dir] = new_root->children[dir];
583 if (new_root->children[dir])
585 new_root->children[dir]->parent = position->children[dir];
589 new_root->children[dir] = position->children[dir];
590 position->children[dir]->parent = new_root;
593 position->weight = third != kNeither && third == dir ? 1 - dir : kNeither;
596 position->children[dir] = new_root->children[1 - dir];
597 if (new_root->children[1 - dir])
599 new_root->children[1 - dir]->parent = position;
603 new_root->parent = position->parent;
604 new_root->children[1 - dir] = position;
605 new_root->dir = 1 - dir;
608 position->parent = new_root;
611 position->weight = kNeither;
617 ETL_DECLARE_DEBUG_COUNT
624 template <
typename TKey,
typename TCompare = ETL_OR_STD::less<TKey> >
629 typedef TKey key_type;
630 typedef TKey value_type;
631 typedef TCompare key_compare;
632 typedef TCompare value_compare;
633 typedef value_type& reference;
634 typedef const value_type& const_reference;
635 #if ETL_CPP11_SUPPORTED
636 typedef value_type&& rvalue_reference;
638 typedef value_type* pointer;
639 typedef const value_type* const_pointer;
665 return compare(node1.value, node2.value);
669 return compare(node.value, key);
673 return compare(key, node.value);
686 static Data_Node* data_cast(Node* p_node)
688 return static_cast<Data_Node*
>(p_node);
694 static Data_Node& data_cast(Node& node)
696 return static_cast<Data_Node&
>(node);
702 static const Data_Node* data_cast(
const Node* p_node)
704 return static_cast<const Data_Node*
>(p_node);
710 static const Data_Node& data_cast(
const Node& node)
712 return static_cast<const Data_Node&
>(node);
727 : p_multiset(ETL_NULLPTR)
728 , p_node(ETL_NULLPTR)
734 , p_node(ETL_NULLPTR)
745 : p_multiset(other.p_multiset)
746 , p_node(other.p_node)
782 p_multiset = other.p_multiset;
783 p_node = other.p_node;
787 reference operator *()
789 return imultiset::data_cast(p_node)->value;
792 const_reference operator *()
const
794 return imultiset::data_cast(p_node)->value;
799 return &(imultiset::data_cast(p_node)->value);
804 return &(imultiset::data_cast(p_node)->value);
807 pointer operator ->()
809 return &(imultiset::data_cast(p_node)->value);
812 const_pointer operator ->()
const
814 return &(imultiset::data_cast(p_node)->value);
819 return lhs.p_multiset == rhs.p_multiset && lhs.p_node == rhs.p_node;
824 return !(lhs == rhs);
848 : p_multiset(ETL_NULLPTR)
849 , p_node(ETL_NULLPTR)
855 , p_node(ETL_NULLPTR)
866 : p_multiset(other.p_multiset)
867 , p_node(other.p_node)
872 : p_multiset(other.p_multiset)
873 , p_node(other.p_node)
909 p_multiset = other.p_multiset;
910 p_node = other.p_node;
914 const_reference operator *()
const
916 return imultiset::data_cast(p_node)->value;
921 return imultiset::data_cast(p_node)->value;
924 const_pointer operator ->()
const
926 return &(imultiset::data_cast(p_node)->value);
931 return lhs.p_multiset == rhs.p_multiset && lhs.p_node == rhs.p_node;
936 return !(lhs == rhs);
949 typedef typename etl::iterator_traits<iterator>::difference_type difference_type;
951 typedef ETL_OR_STD::reverse_iterator<iterator> reverse_iterator;
952 typedef ETL_OR_STD::reverse_iterator<const_iterator> const_reverse_iterator;
1007 return reverse_iterator(
iterator(*
this));
1029 const_reverse_iterator
rend()
const
1057 template <
typename TIterator>
1079 return count_nodes(key);
1088 return ETL_OR_STD::make_pair<iterator, iterator>(
1097 ETL_OR_STD::pair<const_iterator, const_iterator>
equal_range(const_reference key)
const
1099 return ETL_OR_STD::make_pair<const_iterator, const_iterator>(
1121 Node* node =
const_cast<Node*
>(position.p_node);
1138 const_iterator lower(*
this, find_lower_node(
root_node, key_value));
1139 const_iterator upper(*
this, find_upper_node(
root_node, key_value));
1140 while (lower != upper)
1145 (void)
erase(lower++);
1158 while (first != last)
1172 while (first != last)
1174 next =
erase(first++);
1208 Node* inserted_node = ETL_NULLPTR;
1213 Data_Node& node = allocate_data_node(value);
1216 inserted_node = insert_node(
root_node, node);
1219 return iterator(*
this, inserted_node);
1222 #if ETL_CPP11_SUPPORTED
1231 Node* inserted_node = ETL_NULLPTR;
1236 Data_Node& node = allocate_data_node(etl::move(value));
1239 inserted_node = insert_node(
root_node, node);
1242 return iterator(*
this, inserted_node);
1258 #if ETL_CPP11_SUPPORTED
1268 return insert(etl::move(value));
1284 #if ETL_CPP11_SUPPORTED
1294 return insert(etl::move(value));
1305 template <
class TIterator>
1308 while (first != last)
1372 #if ETL_CPP11_SUPPORTED
1383 while (from != rhs.end())
1385 insert(etl::move(*from++));
1416 , p_node_pool(&node_pool)
1427 while (item !=
end())
1438 Data_Node& allocate_data_node(const_reference value)
1440 Data_Node& node = create_data_node();
1441 ::new ((
void*)&node.value) value_type(value);
1442 ETL_INCREMENT_DEBUG_COUNT
1446 #if ETL_CPP11_SUPPORTED
1450 Data_Node& allocate_data_node(rvalue_reference value)
1452 Data_Node& node = create_data_node();
1453 ::new ((
void*)&node.value) value_type(etl::move(value));
1454 ETL_INCREMENT_DEBUG_COUNT
1462 Data_Node& create_data_node()
1464 Data_Node* (
etl::ipool::*func)() = &etl::ipool::allocate<Data_Node>;
1465 return *(p_node_pool->*func)();
1471 void destroy_data_node(Data_Node& node)
1473 node.value.~value_type();
1474 p_node_pool->release(&node);
1475 ETL_DECREMENT_DEBUG_COUNT
1484 size_type result = 0;
1487 const Node* lower = find_lower_node(
root_node, key);
1488 const Node* upper = find_upper_node(
root_node, key);
1491 while (lower != upper)
1494 const Data_Node& data_node = imultiset::data_cast(*lower);
1515 Node* found = ETL_NULLPTR;
1519 Data_Node& data_node = imultiset::data_cast(*position);
1524 position = position->children[kLeft];
1529 position = position->children[kRight];
1535 position = position->children[kLeft];
1546 const Node* find_node(
const Node* position,
key_parameter_t key)
const
1548 const Node* found = ETL_NULLPTR;
1552 const Data_Node& data_node = imultiset::data_cast(*position);
1557 position = position->children[kLeft];
1562 position = position->children[kRight];
1568 position = position->children[kLeft];
1582 Node* lower_node = ETL_NULLPTR;
1586 Data_Node& data_node = imultiset::data_cast(*position);
1590 lower_node = position;
1591 if (position->children[kLeft])
1593 position = position->children[kLeft];
1603 position = position->children[kRight];
1608 lower_node = position;
1609 position = position->children[kLeft];
1623 Node* upper_node = ETL_NULLPTR;
1629 Data_Node& data_node = imultiset::data_cast(*position);
1633 position = position->children[kRight];
1637 upper_node = position;
1639 if (!found && position->children[kLeft])
1641 position = position->children[kLeft];
1663 Node* insert_node(Node*& position, Data_Node& node)
1666 Node* found = position;
1672 Node* critical_parent_node = ETL_NULLPTR;
1679 if (kNeither != found->weight)
1681 critical_node = found;
1685 Data_Node& found_data_node = imultiset::data_cast(*found);
1694 else if (
node_comp(found_data_node, node))
1697 found->dir = kRight;
1703 found->dir = kRight;
1707 if (found->children[found->dir])
1711 if (kNeither != found->children[found->dir]->weight)
1713 critical_parent_node = found;
1717 found = found->children[found->dir];
1722 attach_node(found, found->children[found->dir], node);
1725 found = found->children[found->dir];
1735 if (critical_parent_node == ETL_NULLPTR && critical_node ==
root_node)
1739 else if (critical_parent_node == ETL_NULLPTR && critical_node == position)
1745 if (critical_parent_node != ETL_NULLPTR)
1747 balance_node(critical_parent_node->children[critical_parent_node->dir]);
1769 void remove_node(Node* node)
1775 Data_Node& data_node = imultiset::data_cast(*node);
1790 node->parent->children[kLeft] == node ? kLeft : kRight;
1793 node = node->parent;
1812 node->dir = node->children[kLeft] ? kLeft : kRight;
1823 if ((node->weight == kNeither) ||
1824 (node->weight == (1 - node->dir) &&
1825 node->children[1 - node->dir]->weight == kNeither))
1832 node = node->children[node->dir];
1846 if (node->children[node->dir] == ETL_NULLPTR)
1856 if ((node->weight == kNeither) ||
1857 (node->weight == (1 - node->dir) &&
1858 node->children[1 - node->dir]->weight == kNeither))
1865 node = node->children[node->dir];
1868 Data_Node& replace_data_node = imultiset::data_cast(*node);
1871 if (
node_comp(data_node, replace_data_node))
1876 else if (
node_comp(replace_data_node, data_node))
1884 node->dir = node->children[kLeft] ? kLeft : kRight;
1893 if (balance->children[balance->dir] == ETL_NULLPTR)
1900 if (balance->weight == kNeither)
1902 balance->weight = 1 - balance->dir;
1906 else if (balance->weight == balance->dir)
1908 balance->weight = kNeither;
1913 int weight = balance->children[1 - balance->dir]->weight;
1915 if (weight == balance->dir)
1918 if (balance->parent == ETL_NULLPTR)
1921 balance->children[1 - balance->dir]->children[balance->dir]->weight);
1925 rotate_3node(balance->parent->children[balance->parent->dir], 1 - balance->dir,
1926 balance->children[1 - balance->dir]->children[balance->dir]->weight);
1931 else if (weight == kNeither)
1934 if (balance->parent == ETL_NULLPTR)
1944 Node* old_parent = balance->parent;
1945 rotate_2node(balance->parent->children[balance->parent->dir], 1 - balance->dir);
1946 old_parent->children[old_parent->dir]->weight = balance->dir;
1949 balance->weight = 1 - balance->dir;
1955 if (balance->parent == ETL_NULLPTR)
1961 rotate_2node(balance->parent->children[balance->parent->dir], 1 - balance->dir);
1967 balance = balance->children[balance->dir];
1974 detach_node(found->parent->children[found->parent->dir],
1975 node->parent->children[node->parent->dir]);
1996 destroy_data_node(data_node);
2006 #if defined(ETL_POLYMORPHIC_MULTISET) || defined(ETL_POLYMORPHIC_CONTAINERS)
2022 template <
typename TKey, const
size_t MAX_SIZE_,
typename TCompare = ETL_OR_STD::less<TKey> >
2027 static const size_t MAX_SIZE = MAX_SIZE_;
2047 #if ETL_CPP11_SUPPORTED
2058 while (from != other.end())
2060 this->
insert(etl::move(*from++));
2072 template <
typename TIterator>
2076 this->
assign(first, last);
2079 #if ETL_CPP11_SUPPORTED && ETL_NOT_USING_STLPORT && ETL_USING_STL
2083 multiset(std::initializer_list<
typename etl::imultiset<TKey, TCompare>::value_type> init)
2086 this->
assign(init.begin(), init.end());
2112 #if ETL_CPP11_SUPPORTED
2124 while (from != rhs.end())
2126 this->
insert(etl::move(*from++));
2143 #if ETL_CPP17_SUPPORTED && ETL_NOT_USING_STLPORT && ETL_USING_STL
2144 template <
typename T,
typename... Ts>
2146 ->multiset<etl::enable_if_t<(etl::is_same_v<T, Ts> && ...), T>, 1U +
sizeof...(Ts)>;
2156 template <
typename TKey,
typename TCompare>
2169 template <
typename TKey,
typename TCompare>
2172 return !(lhs == rhs);
2182 template <
typename TKey,
typename TCompare>
2185 return ETL_OR_STD::lexicographical_compare(lhs.
begin(),
2198 template <
typename TKey,
typename TCompare>
2211 template <
typename TKey,
typename TCompare>
2214 return !(lhs > rhs);
2224 template <
typename TKey,
typename TCompare>
2227 return !(lhs < rhs);
const_iterator
Definition: multiset.h:842
iterator.
Definition: multiset.h:720
A templated multiset implementation that uses a fixed size buffer.
Definition: multiset.h:2024
multiset(const multiset &other)
Copy constructor.
Definition: multiset.h:2041
multiset()
Default constructor.
Definition: multiset.h:2032
multiset & operator=(const multiset &rhs)
Assignment operator.
Definition: multiset.h:2101
~multiset()
Destructor.
Definition: multiset.h:2093
multiset(TIterator first, TIterator last)
Definition: multiset.h:2073
bitset< MAXN > operator&(const bitset< MAXN > &lhs, const bitset< MAXN > &rhs)
Definition: bitset.h:1157
#define ETL_ASSERT(b, e)
Definition: error_handler.h:290
Definition: exception.h:47
iterator begin()
Gets the beginning of the multiset.
Definition: multiset.h:957
iterator lower_bound(key_parameter_t key)
Definition: multiset.h:1320
bool full() const
Checks to see if the set is full.
Definition: multiset.h:160
void next_node(const Node *&position) const
Find the next node in sequence from the node provided.
Definition: multiset.h:412
reverse_iterator rbegin()
Gets the reverse beginning of the list.
Definition: multiset.h:1005
iterator insert(const_reference value)
Definition: multiset.h:1205
void clear()
Clears the multiset.
Definition: multiset.h:1067
const_iterator upper_bound(key_parameter_t key) const
Definition: multiset.h:1353
size_type count(key_parameter_t key) const
Definition: multiset.h:1077
void erase(iterator position)
Erases the value at the specified position.
Definition: multiset.h:1107
bool node_comp(const Data_Node &node1, const Data_Node &node2) const
How to compare node elements.
Definition: multiset.h:663
const size_type CAPACITY
The maximum size of the set.
Definition: multiset.h:615
size_t size_type
The type used for determining the size of set.
Definition: multiset.h:131
void rotate_2node(Node *&position, uint_least8_t dir)
Rotate two nodes at the position provided the to balance the tree.
Definition: multiset.h:520
const_reverse_iterator crbegin() const
Gets the reverse beginning of the list.
Definition: multiset.h:1037
iterator insert(iterator, const_reference value)
Definition: multiset.h:1252
iterator erase(const_iterator first, const_iterator last)
Erases a range of elements.
Definition: multiset.h:1169
imultiset & operator=(const imultiset &rhs)
Assignment operator.
Definition: multiset.h:1361
iterator end()
Gets the end of the multiset.
Definition: multiset.h:973
etl::parameter_type< TKey >::type key_parameter_t
Defines the key value parameter type.
Definition: multiset.h:658
const_iterator lower_bound(key_parameter_t key) const
Definition: multiset.h:1331
size_type size() const
Gets the size of the set.
Definition: multiset.h:136
void balance_node(Node *&critical_node)
Balance the critical node at the position provided as needed.
Definition: multiset.h:300
const_iterator end() const
Gets the end of the multiset.
Definition: multiset.h:981
const_iterator cend() const
Gets the end of the multiset.
Definition: multiset.h:997
const_iterator cbegin() const
Gets the beginning of the multiset.
Definition: multiset.h:989
iterator find(key_parameter_t key_value)
Definition: multiset.h:1185
void next_node(Node *&position) const
Find the next node in sequence from the node provided.
Definition: multiset.h:380
void initialise()
Initialise the multiset.
Definition: multiset.h:1423
void assign(TIterator first, TIterator last)
Definition: multiset.h:1058
iterator erase(iterator first, iterator last)
Erases a range of elements.
Definition: multiset.h:1155
const_iterator find(key_parameter_t key_value) const
Definition: multiset.h:1195
size_type capacity() const
Definition: multiset.h:169
reverse_iterator rend()
Gets the reverse end of the list.
Definition: multiset.h:1021
void attach_node(Node *parent, Node *&position, Node &node)
Attach the provided node to the position provided.
Definition: multiset.h:244
const_iterator begin() const
Gets the beginning of the multiset.
Definition: multiset.h:965
void prev_node(Node *&position) const
Find the previous node in sequence from the node provided.
Definition: multiset.h:444
void prev_node(const Node *&position) const
Find the previous node in sequence from the node provided.
Definition: multiset.h:482
imultiset(etl::ipool &node_pool, size_t max_size_)
Constructor.
Definition: multiset.h:1414
Node * root_node
The node that acts as the multiset root.
Definition: multiset.h:616
size_type max_size() const
Gets the maximum possible size of the set.
Definition: multiset.h:144
const_reverse_iterator rend() const
Gets the reverse end of the list.
Definition: multiset.h:1029
~imultiset()
Destructor.
Definition: multiset.h:2013
Node * find_limit_node(Node *position, const int8_t dir) const
Definition: multiset.h:364
void insert(TIterator first, TIterator last)
Definition: multiset.h:1306
value_compare value_comp() const
How to compare two value elements.
Definition: multiset.h:1404
~multiset_base()
Destructor.
Definition: multiset.h:237
iterator insert(const_iterator, const_reference value)
Definition: multiset.h:1278
multiset_base(size_type max_size_)
The constructor that is called from derived classes.
Definition: multiset.h:227
ETL_OR_STD::pair< const_iterator, const_iterator > equal_range(const_reference key) const
Definition: multiset.h:1097
iterator upper_bound(key_parameter_t key)
Definition: multiset.h:1342
key_compare key_comp() const
How to compare two key elements.
Definition: multiset.h:1396
iterator erase(const_iterator position)
Erases the value at the specified position.
Definition: multiset.h:1116
const_reverse_iterator rbegin() const
Gets the reverse beginning of the list.
Definition: multiset.h:1013
void detach_node(Node *&position, Node *&replacement)
Detach the node at the position provided.
Definition: multiset.h:262
const_reverse_iterator crend() const
Gets the reverse end of the list.
Definition: multiset.h:1045
ETL_OR_STD::pair< iterator, iterator > equal_range(const_reference key)
Definition: multiset.h:1086
bool empty() const
Checks to see if the set is empty.
Definition: multiset.h:152
size_type current_size
The number of the used nodes.
Definition: multiset.h:614
size_t available() const
Definition: multiset.h:178
void rotate_3node(Node *&position, uint_least8_t dir, uint_least8_t third)
Rotate three nodes at the position provided the to balance the tree.
Definition: multiset.h:561
Definition: multiset.h:626
Definition: multiset.h:128
Definition: multiset.h:72
Definition: multiset.h:86
Definition: multiset.h:114
Definition: multiset.h:100
Definition: absolute.h:37
bool operator==(const etl::imultiset< TKey, TCompare > &lhs, const etl::imultiset< TKey, TCompare > &rhs)
Template deduction guides.
Definition: multiset.h:2157
bool operator>(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition: array.h:633
bool operator>=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition: array.h:645
bool operator!=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition: array.h:594
void swap(etl::array< T, SIZE > &lhs, etl::array< T, SIZE > &rhs)
Template deduction guides.
Definition: array.h:570
bool operator!=(const etl::imultiset< TKey, TCompare > &lhs, const etl::imultiset< TKey, TCompare > &rhs)
Definition: multiset.h:2170
bool operator==(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition: array.h:582
bool operator<(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition: array.h:606
bool operator<=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition: array.h:621
The data node element in the multiset.
Definition: multiset.h:648
iterator
Definition: iterator.h:422
The node element in the multiset.
Definition: multiset.h:196
void mark_as_leaf()
Marks the node as a leaf.
Definition: multiset.h:209
Node()
Constructor.
Definition: multiset.h:200
etl::conditional< etl::is_fundamental< T >::value||etl::is_pointer< T >::value, T, const T & >::type type
By default fundamental and pointer types are passed by value.
Definition: parameter_type.h:48