NexusForce 1.0.0
A rigorously engineered full-stack C++ backend library.
载入中...
搜索中...
未找到
sparse_vector.hpp
浏览该文件的文档.
1#ifndef NEFORCE_CORE_CONTAINER_SPARSE_VECTOR_HPP__
2#define NEFORCE_CORE_CONTAINER_SPARSE_VECTOR_HPP__
3
13
21NEFORCE_BEGIN_NAMESPACE__
22
48
57template <bool IsConst, typename SparseVector>
58struct sparse_vector_iterator : iiterator<sparse_vector_iterator<IsConst, SparseVector>> {
59public:
60 using container_type = SparseVector;
61 using value_type = typename container_type::value_type;
62 using size_type = typename container_type::size_type;
63 using difference_type = typename container_type::difference_type;
65 using reference = conditional_t<IsConst, typename container_type::const_reference,
66 typename container_type::reference>;
67 using pointer = conditional_t<IsConst, typename container_type::const_pointer,
68 typename container_type::pointer>;
69
70private:
71 const container_type* container_ = nullptr;
72 size_type index_ = 0;
73
74 template <typename, typename, typename, typename, typename>
75 friend class sparse_vector;
76
77public:
78 sparse_vector_iterator() noexcept = default;
79 ~sparse_vector_iterator() = default;
80
81 sparse_vector_iterator(const sparse_vector_iterator&) noexcept = default;
82 sparse_vector_iterator& operator=(const sparse_vector_iterator&) noexcept = default;
83 sparse_vector_iterator(sparse_vector_iterator&&) noexcept = default;
84 sparse_vector_iterator& operator=(sparse_vector_iterator&&) noexcept = default;
85
91 sparse_vector_iterator(size_type index, const container_type* container) noexcept :
92 container_(container),
93 index_(index) {}
94
99 NEFORCE_NODISCARD reference dereference() const noexcept {
100 NEFORCE_DEBUG_VERIFY(container_ != nullptr, "Attempting to dereference on null container");
101 NEFORCE_DEBUG_VERIFY(index_ < container_->size(), "Attempting to dereference out of boundary");
102 return const_cast<container_type*>(container_)->data_[index_];
103 }
104
108 NEFORCE_CONSTEXPR20 void increment() noexcept {
109 NEFORCE_DEBUG_VERIFY(container_ != nullptr, "Attempting to increment null container");
110 NEFORCE_DEBUG_VERIFY(index_ <= container_->size(), "Attempting to increment out of boundary");
111 ++index_;
112 }
113
117 NEFORCE_CONSTEXPR20 void decrement() noexcept {
118 NEFORCE_DEBUG_VERIFY(container_ != nullptr, "Attempting to decrement null container");
119 NEFORCE_DEBUG_VERIFY(index_ > 0, "Attempting to decrement before begin");
120 --index_;
121 }
122
127 void advance(difference_type n) noexcept {
128 NEFORCE_DEBUG_VERIFY(container_ != nullptr, "Attempting to advance null container");
129 index_ = static_cast<size_type>(static_cast<difference_type>(index_) + n);
130 }
131
137 NEFORCE_NODISCARD difference_type distance_to(const sparse_vector_iterator& rhs) const noexcept {
138 NEFORCE_DEBUG_VERIFY(container_ == rhs.container_, "Attempting to distance different container");
139 return static_cast<difference_type>(rhs.index_) - static_cast<difference_type>(index_);
140 }
141
147 NEFORCE_NODISCARD bool equal_to(const sparse_vector_iterator& rhs) const noexcept {
148 NEFORCE_DEBUG_VERIFY(container_ == rhs.container_, "Attempting to equal to a different container");
149 return index_ == rhs.index_;
150 }
151
157 NEFORCE_NODISCARD bool less_than(const sparse_vector_iterator& rhs) const noexcept {
158 NEFORCE_DEBUG_VERIFY(container_ == rhs.container_, "Attempting to less than a different container");
159 return index_ < rhs.index_;
160 }
161
166 NEFORCE_NODISCARD const container_type* container() const noexcept { return container_; }
167
172 NEFORCE_NODISCARD size_type index() const noexcept { return index_; }
173};
174
175
190template <typename Key, typename Value, typename KeyOfValue, typename Compare, typename Alloc = allocator<Value>>
191class sparse_vector : icollector<sparse_vector<Key, Value, KeyOfValue, Compare, Alloc>> {
192 static_assert(is_allocator_v<Alloc>, "Alloc type is not a standard allocator type.");
193 static_assert(is_same_v<Value, typename Alloc::value_type>, "allocator type mismatch.");
194 static_assert(is_object_v<Value>, "sparse_vector only contains object types.");
195
196public:
197 using key_type = Key;
198
199 using value_type = Value;
200 using pointer = Value*;
201 using reference = Value&;
202 using const_pointer = const Value*;
203 using const_reference = const Value&;
206 using compare_type = Compare;
207
208 using iterator = sparse_vector_iterator<false, sparse_vector>;
209 using const_iterator = sparse_vector_iterator<true, sparse_vector>;
212 using allocator_type = Alloc;
213
214private:
215 using container_type = vector<Value, Alloc>;
216
217 container_type data_;
218 Compare key_compare_{};
219 KeyOfValue extracter_{};
220
221 template <bool, typename>
222 friend struct sparse_vector_iterator;
223
229 NEFORCE_NODISCARD const Key& key_of(const value_type& value) const noexcept { return extracter_(value); }
230
236 NEFORCE_NODISCARD size_type lower_bound_index(const key_type& key) const {
237 size_type lo = 0;
238 size_type hi = data_.size();
239 while (lo < hi) {
240 size_type mid = lo + (hi - lo) / 2;
241 if (key_compare_(key_of(data_[mid]), key)) {
242 lo = mid + 1;
243 } else {
244 hi = mid;
245 }
246 }
247 return lo;
248 }
249
255 NEFORCE_NODISCARD size_type upper_bound_index(const key_type& key) const {
256 size_type lo = 0;
257 size_type hi = data_.size();
258 while (lo < hi) {
259 size_type mid = lo + (hi - lo) / 2;
260 if (key_compare_(key, key_of(data_[mid]))) {
261 hi = mid;
262 } else {
263 lo = mid + 1;
264 }
265 }
266 return lo;
267 }
268
275 iterator insert_at(size_type pos, value_type&& value) {
276 data_.emplace(data_.begin() + static_cast<difference_type>(pos), _NEFORCE move(value));
277 return iterator(pos, this);
278 }
279
286 iterator insert_at(size_type pos, const value_type& value) {
287 data_.emplace(data_.begin() + static_cast<difference_type>(pos), value);
288 return iterator(pos, this);
289 }
290
291public:
295 sparse_vector() = default;
296
301 explicit sparse_vector(const Compare& comp) :
302 key_compare_(comp) {}
303
309 data_(other.data_),
310 key_compare_(other.key_compare_),
311 extracter_(other.extracter_) {}
312
319 if (_NEFORCE addressof(other) == this) {
320 return *this;
321 }
322 data_ = other.data_;
323 key_compare_ = other.key_compare_;
324 extracter_ = other.extracter_;
325 return *this;
326 }
327
335 data_(_NEFORCE move(other.data_)),
336 key_compare_(_NEFORCE move(other.key_compare_)),
337 extracter_(_NEFORCE move(other.extracter_)) {}
338
345 if (_NEFORCE addressof(other) == this) {
346 return *this;
347 }
348 data_ = _NEFORCE move(other.data_);
349 key_compare_ = _NEFORCE move(other.key_compare_);
350 extracter_ = _NEFORCE move(other.extracter_);
351 return *this;
352 }
353
357 ~sparse_vector() = default;
358
363 NEFORCE_NODISCARD iterator begin() noexcept { return iterator(0, this); }
364
369 NEFORCE_NODISCARD iterator end() noexcept { return iterator(data_.size(), this); }
370
375 NEFORCE_NODISCARD const_iterator begin() const noexcept { return cbegin(); }
376
381 NEFORCE_NODISCARD const_iterator end() const noexcept { return cend(); }
382
387 NEFORCE_NODISCARD const_iterator cbegin() const noexcept { return const_iterator(0, this); }
388
393 NEFORCE_NODISCARD const_iterator cend() const noexcept { return const_iterator(data_.size(), this); }
394
399 NEFORCE_NODISCARD reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
400
405 NEFORCE_NODISCARD reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
406
411 NEFORCE_NODISCARD const_reverse_iterator rbegin() const noexcept { return crbegin(); }
412
417 NEFORCE_NODISCARD const_reverse_iterator rend() const noexcept { return crend(); }
418
423 NEFORCE_NODISCARD const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(cend()); }
424
429 NEFORCE_NODISCARD const_reverse_iterator crend() const noexcept { return const_reverse_iterator(cbegin()); }
430
435 NEFORCE_NODISCARD size_type size() const noexcept { return data_.size(); }
436
441 NEFORCE_NODISCARD size_type max_size() const noexcept { return data_.max_size(); }
442
447 NEFORCE_NODISCARD bool empty() const noexcept { return data_.empty(); }
448
453 NEFORCE_NODISCARD Compare key_compare() const noexcept(is_nothrow_copy_constructible_v<Compare>) {
454 return key_compare_;
455 }
456
463 template <typename... Args>
465 value_type tmp(_NEFORCE forward<Args>(args)...);
466 size_type pos = lower_bound_index(key_of(tmp));
467 if (pos < data_.size() && !key_compare_(key_of(tmp), key_of(data_[pos]))) {
468 return pair<iterator, bool>(iterator(pos, this), false);
469 }
470 return pair<iterator, bool>(insert_at(pos, _NEFORCE move(tmp)), true);
471 }
472
479
486
494 template <typename... Args>
495 iterator emplace_unique_hint(iterator position, Args&&... args) {
496 value_type tmp(_NEFORCE forward<Args>(args)...);
497 const key_type& k = key_of(tmp);
498
499 if (position != end() && position != begin()) {
500 iterator before = position;
501 --before;
502 if (key_compare_(key_of(*before), k) && key_compare_(k, key_of(*position))) {
503 return insert_at(position.index(), _NEFORCE move(tmp));
504 }
505 }
506 if (position == begin() && !data_.empty()) {
507 if (key_compare_(k, key_of(data_.front()))) {
508 return insert_at(0, _NEFORCE move(tmp));
509 }
510 if (!key_compare_(key_of(data_.front()), k)) {
511 return iterator(0, this);
512 }
513 }
514 if (position == end() && !data_.empty()) {
515 if (key_compare_(key_of(data_.back()), k)) {
516 return insert_at(data_.size(), _NEFORCE move(tmp));
517 }
518 if (!key_compare_(k, key_of(data_.back()))) {
519 return iterator(data_.size() - 1, this);
520 }
521 }
522
523 return emplace_unique(_NEFORCE move(tmp)).first;
524 }
525
532 iterator insert_unique(iterator position, const value_type& value) { return emplace_unique_hint(position, value); }
533
541 return emplace_unique_hint(position, _NEFORCE move(value));
542 }
543
550 template <typename Iterator, enable_if_t<is_iter_v<Iterator>, int> = 0>
551 void insert_unique(Iterator first, Iterator last) {
552 for (; first != last; ++first) {
553 insert_unique(*first);
554 }
555 }
556
563 template <typename... Args>
564 iterator emplace_equal(Args&&... args) {
565 value_type tmp(_NEFORCE forward<Args>(args)...);
566 size_type pos = upper_bound_index(key_of(tmp));
567 return insert_at(pos, _NEFORCE move(tmp));
568 }
569
575 iterator insert_equal(const value_type& value) { return emplace_equal(value); }
576
582 iterator insert_equal(value_type&& value) { return emplace_equal(_NEFORCE move(value)); }
583
591 template <typename... Args>
592 iterator emplace_equal_hint(iterator position, Args&&... args) {
593 value_type tmp(_NEFORCE forward<Args>(args)...);
594 const key_type& k = key_of(tmp);
595
596 if (position != end() && position != begin()) {
597 iterator before = position;
598 --before;
599 if (key_compare_(key_of(*before), k) && key_compare_(k, key_of(*position))) {
600 return insert_at(position.index(), _NEFORCE move(tmp));
601 }
602 }
603 if (position == begin() && !data_.empty()) {
604 if (key_compare_(k, key_of(data_.front()))) {
605 return insert_at(0, _NEFORCE move(tmp));
606 }
607 }
608 if (position == end() && !data_.empty()) {
609 if (!key_compare_(k, key_of(data_.back()))) {
610 return insert_at(data_.size(), _NEFORCE move(tmp));
611 }
612 }
613
614 return emplace_equal(_NEFORCE move(tmp));
615 }
616
623 iterator insert_equal(iterator position, const value_type& value) { return emplace_equal_hint(position, value); }
624
632 return emplace_equal_hint(position, _NEFORCE move(value));
633 }
634
641 template <typename Iterator, enable_if_t<is_iter_v<Iterator>, int> = 0>
642 void insert_equal(Iterator first, Iterator last) {
643 for (; first != last; ++first) {
644 insert_equal(*first);
645 }
646 }
647
654 size_type lo = lower_bound_index(key);
655 size_type hi = upper_bound_index(key);
656 size_type n = hi - lo;
657 if (n > 0) {
658 data_.erase(data_.begin() + static_cast<difference_type>(lo),
659 data_.begin() + static_cast<difference_type>(hi));
660 }
661 return n;
662 }
663
668 void erase(iterator position) {
669 NEFORCE_DEBUG_VERIFY(position.container() == this, "Attempting to erase from different container");
670 NEFORCE_DEBUG_VERIFY(position.index() < data_.size(), "Attempting to erase out of boundary");
671 data_.erase(data_.begin() + static_cast<difference_type>(position.index()));
672 }
673
679 void erase(iterator first, iterator last) {
680 NEFORCE_DEBUG_VERIFY(first.container() == this && last.container() == this,
681 "Attempting to erase from different container");
682 if (first == begin() && last == end()) {
683 clear();
684 } else {
685 data_.erase(data_.begin() + static_cast<difference_type>(first.index()),
686 data_.begin() + static_cast<difference_type>(last.index()));
687 }
688 }
689
693 void clear() { data_.clear(); }
694
700 NEFORCE_NODISCARD iterator find(const key_type& key) {
701 size_type pos = lower_bound_index(key);
702 if (pos < data_.size() && !key_compare_(key, key_of(data_[pos]))) {
703 return iterator(pos, this);
704 }
705 return end();
706 }
707
713 NEFORCE_NODISCARD const_iterator find(const key_type& key) const {
714 size_type pos = lower_bound_index(key);
715 if (pos < data_.size() && !key_compare_(key, key_of(data_[pos]))) {
716 return const_iterator(pos, this);
717 }
718 return cend();
719 }
720
726 NEFORCE_NODISCARD size_type count(const key_type& key) const {
727 return upper_bound_index(key) - lower_bound_index(key);
728 }
729
735 NEFORCE_NODISCARD iterator lower_bound(const key_type& key) { return iterator(lower_bound_index(key), this); }
736
742 NEFORCE_NODISCARD const_iterator lower_bound(const key_type& key) const {
743 return const_iterator(lower_bound_index(key), this);
744 }
745
751 NEFORCE_NODISCARD iterator upper_bound(const key_type& key) { return iterator(upper_bound_index(key), this); }
752
758 NEFORCE_NODISCARD const_iterator upper_bound(const key_type& key) const {
759 return const_iterator(upper_bound_index(key), this);
760 }
761
767 NEFORCE_NODISCARD pair<iterator, iterator> equal_range(const key_type& key) {
769 }
770
779
784 void reserve(size_type n) { data_.reserve(n); }
785
790 NEFORCE_NODISCARD size_type capacity() const noexcept { return data_.capacity(); }
791
795 void shrink_to_fit() { data_.shrink_to_fit(); }
796
803 data_.swap(other.data_);
804 _NEFORCE swap(key_compare_, other.key_compare_);
805 _NEFORCE swap(extracter_, other.extracter_);
806 }
807
813 NEFORCE_NODISCARD bool equal_to(const sparse_vector& rhs) const
814 noexcept(noexcept(_NEFORCE equal(cbegin(), cend(), rhs.cbegin()))) {
815 return size() == rhs.size() && _NEFORCE equal(cbegin(), cend(), rhs.cbegin());
816 }
817
823 NEFORCE_NODISCARD bool less_than(const sparse_vector& rhs) const
824 noexcept(noexcept(_NEFORCE lexicographical_compare(cbegin(), cend(), rhs.cbegin(), rhs.cend()))) {
825 return _NEFORCE lexicographical_compare(cbegin(), cend(), rhs.cbegin(), rhs.cend());
826 }
827};
828 // SparseVector
830
831NEFORCE_END_NAMESPACE__
832#endif // NEFORCE_CORE_CONTAINER_SPARSE_VECTOR_HPP__
比较算法
iterator lower_bound(const key_type &key)
获取第一个不小于指定键的元素位置
const_reverse_iterator rbegin() const noexcept
获取常量反向起始迭代器
iterator insert_equal(iterator position, const value_type &value)
在提示位置附近拷贝插入允许重复键元素
size_type count(const key_type &key) const
统计具有指定键的元素数量
iterator begin() noexcept
获取起始迭代器
reverse_iterator rend() noexcept
获取反向结束迭代器
iterator insert_unique(iterator position, const value_type &value)
在提示位置附近拷贝插入唯一键元素
void shrink_to_fit()
收缩容量以适应实际大小
pair< iterator, bool > insert_unique(const value_type &value)
拷贝插入唯一键元素
pair< const_iterator, const_iterator > equal_range(const key_type &key) const
获取等于指定键的元素范围(常量版本)
sparse_vector()=default
默认构造函数
sparse_vector & operator=(const sparse_vector &other)
拷贝赋值运算符
const_reverse_iterator rend() const noexcept
获取常量反向结束迭代器
iterator find(const key_type &key)
查找具有指定键的元素
void erase(iterator position)
删除指定位置的元素
sparse_vector(const sparse_vector &other)
拷贝构造函数
iterator emplace_equal_hint(iterator position, Args &&... args)
在提示位置附近构造允许重复键元素
bool equal_to(const sparse_vector &rhs) const noexcept(noexcept(_NEFORCE equal(cbegin(), cend(), rhs.cbegin())))
相等比较
Compare key_compare() const noexcept(is_nothrow_copy_constructible_v< Compare >)
获取键比较函数对象
void insert_equal(Iterator first, Iterator last)
范围插入允许重复键元素
pair< iterator, iterator > equal_range(const key_type &key)
获取等于指定键的元素范围
const_iterator lower_bound(const key_type &key) const
获取第一个不小于指定键的元素位置(常量版本)
size_type erase(const key_type &key)
删除所有具有指定键的元素
bool less_than(const sparse_vector &rhs) const noexcept(noexcept(_NEFORCE lexicographical_compare(cbegin(), cend(), rhs.cbegin(), rhs.cend())))
小于比较
const_iterator begin() const noexcept
获取常量起始迭代器
const_iterator upper_bound(const key_type &key) const
获取第一个大于指定键的元素位置(常量版本)
sparse_vector(sparse_vector &&other) noexcept(is_nothrow_move_constructible_v< container_type > &&is_nothrow_move_constructible_v< Compare > &&is_nothrow_move_constructible_v< KeyOfValue >)
移动构造函数
pair< iterator, bool > emplace_unique(Args &&... args)
插入唯一键元素
iterator end() noexcept
获取结束迭代器
size_type size() const noexcept
获取元素数量
const_iterator find(const key_type &key) const
查找具有指定键的元素(常量版本)
iterator emplace_equal(Args &&... args)
插入允许重复键元素
iterator insert_unique(iterator position, value_type &&value)
在提示位置附近移动插入唯一键元素
void reserve(size_type n)
预留容量
bool empty() const noexcept
检查是否为空
iterator insert_equal(iterator position, value_type &&value)
在提示位置附近移动插入允许重复键元素
pair< iterator, bool > insert_unique(value_type &&value)
移动插入唯一键元素
iterator insert_equal(const value_type &value)
拷贝插入允许重复键元素
iterator emplace_unique_hint(iterator position, Args &&... args)
在提示位置附近构造唯一键元素
const_iterator end() const noexcept
获取常量结束迭代器
void erase(iterator first, iterator last)
删除指定范围内的元素
iterator upper_bound(const key_type &key)
获取第一个大于指定键的元素位置
size_type max_size() const noexcept
获取最大可能大小
size_type capacity() const noexcept
获取当前容量
reverse_iterator rbegin() noexcept
获取反向起始迭代器
iterator insert_equal(value_type &&value)
移动插入允许重复键元素
~sparse_vector()=default
析构函数
sparse_vector(const Compare &comp)
构造函数,指定比较函数
sparse_vector & operator=(sparse_vector &&other) noexcept(is_nothrow_move_assignable_v< container_type >)
移动赋值运算符
void insert_unique(Iterator first, Iterator last)
范围插入唯一键元素
void swap(sparse_vector &other) noexcept(is_nothrow_swappable_v< container_type > &&is_nothrow_swappable_v< Compare > &&is_nothrow_swappable_v< KeyOfValue >)
交换两个稀疏向量的内容
动态大小数组容器
constexpr iterator begin() noexcept
获取起始迭代器
constexpr size_type size() const noexcept
获取当前元素数量
constexpr void emplace(iterator position, Args &&... args)
在指定位置构造元素
内存构造和销毁函数
constexpr T * addressof(T &x) noexcept
获取对象的地址
constexpr T && forward(remove_reference_t< T > &x) noexcept
完美转发左值
constexpr bool is_object_v
is_object的便捷变量模板
constexpr bool equal(Iterator1 first1, Iterator1 last1, Iterator2 first2, BinaryPredicate binary_pred) noexcept(noexcept(++first1) &&noexcept(++first2) &&noexcept(binary_pred(*first1, *first2)))
比较两个范围是否相等
constexpr bool lexicographical_compare(Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2, Compare comp) noexcept(noexcept(++first1) &&noexcept(++first2) &&noexcept(comp(*first1, *first2)) &&noexcept(first1==last1 &&first2 !=last2))
字典序比较两个范围
uint64_t size_t
无符号大小类型
int64_t ptrdiff_t
指针差类型
constexpr Iterator2 move(Iterator1 first, Iterator1 last, Iterator2 result) noexcept(noexcept(inner::__move_aux(first, last, result)))
移动范围元素
constexpr bool is_nothrow_swappable_v
is_nothrow_swappable的便捷变量模板
constexpr bool is_allocator_v
is_allocator的便捷变量模板
constexpr decltype(auto) size(const Container &cont) noexcept(noexcept(cont.size()))
获取容器的大小
constexpr bool is_nothrow_move_assignable_v
is_nothrow_move_assignable的便捷变量模板
constexpr bool is_nothrow_copy_constructible_v
is_nothrow_copy_constructible的便捷变量模板
constexpr bool is_nothrow_move_constructible_v
is_nothrow_move_constructible的便捷变量模板
constexpr bool is_same_v
is_same的便捷变量模板
typename conditional< Test, T1, T2 >::type conditional_t
conditional的便捷别名
集合器接口
迭代器接口
键值对
标准分配器
集合器接口模板
迭代器接口模板
存储两个值的元组对
typename container_type::value_type value_type
值类型
constexpr void increment() noexcept
递增操作
bool equal_to(const sparse_vector_iterator &rhs) const noexcept
相等比较
conditional_t< IsConst, typename container_type::const_pointer, typename container_type::pointer > pointer
指针类型
bool less_than(const sparse_vector_iterator &rhs) const noexcept
小于比较
difference_type distance_to(const sparse_vector_iterator &rhs) const noexcept
计算到另一迭代器的距离
void advance(difference_type n) noexcept
随机访问递增
typename container_type::difference_type difference_type
差值类型
typename container_type::size_type size_type
大小类型
conditional_t< IsConst, typename container_type::const_reference, typename container_type::reference > reference
引用类型
constexpr void decrement() noexcept
递减操作
random_access_iterator_tag iterator_category
随机访问迭代器
reference dereference() const noexcept
解引用操作
SparseVector container_type
容器类型
动态大小数组容器