|
@@ -239,25 +239,26 @@ struct rbtree {
|
|
|
|
|
|
using node_allocator = typename
|
|
|
std::allocator_traits<Allocator>::template rebind_alloc<node>;
|
|
|
+ using node_alloc_traits = std::allocator_traits<node_allocator>;
|
|
|
|
|
|
node* root;
|
|
|
+ std::size_t _size;
|
|
|
Compare comp;
|
|
|
node_allocator alloc;
|
|
|
|
|
|
private:
|
|
|
- template <typename UKey>
|
|
|
- constexpr node* newnode(UKey&& key)
|
|
|
+ template <typename... Args>
|
|
|
+ constexpr node* newnode(Args&&... key)
|
|
|
{
|
|
|
- node* ptr = std::allocator_traits<node_allocator>::allocate(alloc, 1);
|
|
|
- std::allocator_traits<node_allocator>::construct(
|
|
|
- alloc, ptr, std::forward<UKey>(key));
|
|
|
+ node* ptr = node_alloc_traits::allocate(alloc, 1);
|
|
|
+ node_alloc_traits::construct(alloc, ptr, std::forward<Args>(key)...);
|
|
|
return ptr;
|
|
|
}
|
|
|
|
|
|
constexpr void delnode(node* nd)
|
|
|
{
|
|
|
- std::allocator_traits<node_allocator>::destroy(alloc, nd);
|
|
|
- std::allocator_traits<node_allocator>::deallocate(alloc, nd, 1);
|
|
|
+ node_alloc_traits::destroy(alloc, nd);
|
|
|
+ node_alloc_traits::deallocate(alloc, nd, 1);
|
|
|
}
|
|
|
|
|
|
public:
|
|
@@ -284,7 +285,7 @@ public:
|
|
|
delnode(nd);
|
|
|
}
|
|
|
|
|
|
- constexpr void destroy() { destroy(root); root = nullptr; }
|
|
|
+ constexpr void destroy() { destroy(root); root = nullptr; _size = 0; }
|
|
|
|
|
|
constexpr node* copy(node* nd)
|
|
|
{
|
|
@@ -293,6 +294,7 @@ public:
|
|
|
|
|
|
node* newnd = newnode(nd->value);
|
|
|
newnd->color = nd->color;
|
|
|
+ ++_size;
|
|
|
|
|
|
newnd->left = copy(nd->left);
|
|
|
if (newnd->left)
|
|
@@ -306,7 +308,7 @@ public:
|
|
|
}
|
|
|
|
|
|
explicit constexpr rbtree(const Compare& comp, const node_allocator& alloc)
|
|
|
- : root(), comp(comp), alloc(alloc) {}
|
|
|
+ : root(), _size(), comp(comp), alloc(alloc) {}
|
|
|
|
|
|
constexpr rbtree(const rbtree& other)
|
|
|
: rbtree(other.comp, other.alloc)
|
|
@@ -326,10 +328,12 @@ public:
|
|
|
|
|
|
constexpr rbtree(rbtree&& other) noexcept
|
|
|
: root(std::exchange(other.root, nullptr))
|
|
|
+ , _size(std::exchange(other._size, 0))
|
|
|
, comp(std::move(other.comp)), alloc(std::move(other.alloc)) {}
|
|
|
|
|
|
constexpr rbtree(rbtree&& other, const node_allocator& alloc) noexcept
|
|
|
: root(std::exchange(other.root, nullptr))
|
|
|
+ , _size(std::exchange(other._size, 0))
|
|
|
, comp(std::move(other.comp)), alloc(alloc) {}
|
|
|
|
|
|
constexpr ~rbtree() { destroy(); }
|
|
@@ -339,7 +343,8 @@ public:
|
|
|
destroy(root);
|
|
|
|
|
|
comp = other.comp;
|
|
|
- alloc = other.alloc;
|
|
|
+ if constexpr (node_alloc_traits::propagate_on_copy_assignment::value)
|
|
|
+ alloc = other.alloc;
|
|
|
|
|
|
root = copy(other.root);
|
|
|
if (root)
|
|
@@ -350,8 +355,10 @@ public:
|
|
|
{
|
|
|
destroy(root);
|
|
|
root = std::exchange(other.root, nullptr);
|
|
|
+ _size = std::exchange(other._size, 0);
|
|
|
comp = std::move(other.comp);
|
|
|
- alloc = std::move(other.alloc);
|
|
|
+ if constexpr (node_alloc_traits::propagate_on_move_assignment::value)
|
|
|
+ alloc = std::move(other.alloc);
|
|
|
}
|
|
|
|
|
|
constexpr void rotateleft(node* rt)
|
|
@@ -571,6 +578,7 @@ public:
|
|
|
{
|
|
|
node* nextpos = erase(pos.p);
|
|
|
delnode(pos.p);
|
|
|
+ --_size;
|
|
|
return iterator { nextpos };
|
|
|
}
|
|
|
|
|
@@ -578,6 +586,7 @@ public:
|
|
|
{
|
|
|
node* nextpos = erase(pos.p);
|
|
|
delnode(pos.p);
|
|
|
+ --_size;
|
|
|
return const_iterator { nextpos };
|
|
|
}
|
|
|
|
|
@@ -593,6 +602,7 @@ public:
|
|
|
nd->parent = cur;
|
|
|
cur->left = nd;
|
|
|
this->balance(nd);
|
|
|
+ ++_size;
|
|
|
return;
|
|
|
} else {
|
|
|
cur = cur->left;
|
|
@@ -602,6 +612,7 @@ public:
|
|
|
nd->parent = cur;
|
|
|
cur->right = nd;
|
|
|
this->balance(nd);
|
|
|
+ ++_size;
|
|
|
return;
|
|
|
} else {
|
|
|
cur = cur->right;
|
|
@@ -611,6 +622,7 @@ public:
|
|
|
|
|
|
root = nd;
|
|
|
root->toblack();
|
|
|
+ ++_size;
|
|
|
}
|
|
|
|
|
|
template <typename U>
|
|
@@ -626,7 +638,30 @@ public:
|
|
|
return { iterator { ptr }, true };
|
|
|
}
|
|
|
|
|
|
+ template <typename... Args>
|
|
|
+ constexpr std::pair<iterator, bool> emplace(Args&&... args)
|
|
|
+ {
|
|
|
+ node* nd = newnode(std::forward<Args>(args)...);
|
|
|
+ node* exist_nd = _find(nd->value);
|
|
|
+ if (exist_nd) {
|
|
|
+ delnode(nd);
|
|
|
+ return { iterator { exist_nd }, false };
|
|
|
+ }
|
|
|
+ insert(nd);
|
|
|
+ return { iterator { nd }, true };
|
|
|
+ }
|
|
|
+
|
|
|
constexpr bool empty() const noexcept { return !root; }
|
|
|
+ constexpr std::size_t size() const noexcept { return _size; }
|
|
|
+
|
|
|
+ constexpr void swap(rbtree& other)
|
|
|
+ {
|
|
|
+ std::swap(root, other.root);
|
|
|
+ std::swap(_size, other._size);
|
|
|
+ std::swap(comp, other.comp);
|
|
|
+ if constexpr (node_alloc_traits::propagate_on_container_swap::value)
|
|
|
+ std::swap(alloc, other.alloc);
|
|
|
+ }
|
|
|
};
|
|
|
|
|
|
} // namespace std::impl
|