10 #ifndef SYMBOLIC_UTILS_HASH_SET_H_
11 #define SYMBOLIC_UTILS_HASH_SET_H_
17 #include "symbolic/utils/unique_vector.h"
21 constexpr
int HASH_SET_INITIAL_SIZE = 1;
33 HashSet() : buckets_(HASH_SET_INITIAL_SIZE){};
35 HashSet(std::initializer_list<T> l) : buckets_(HASH_SET_INITIAL_SIZE) {
36 for (
const T& element : l) {
58 bool empty()
const {
return size() == 0; }
59 size_t size()
const {
return size_; }
61 size_t bucket_count()
const {
return buckets_.size(); }
63 template <
typename T_query>
64 bool contains(
const T_query& element)
const {
65 return GetBucket(element).contains(element);
68 template <
typename T_query>
69 bool insert(
const T_query& element) {
70 const bool inserted = GetBucket(element).insert(element);
73 if (size() > buckets_.size()) Rehash(UpperBound());
78 bool insert(T&& element) {
79 const bool inserted = GetBucket(element).insert(std::move(element));
82 if (size() > buckets_.size()) Rehash(UpperBound());
87 template <
typename T_query>
88 bool erase(
const T_query& element) {
89 const bool erased = GetBucket(element).erase(element);
92 if (size() <= LowerBound()) Rehash(LowerBound());
98 return lhs.buckets_ == rhs.buckets_;
101 return !(lhs == rhs);
105 return lhs.buckets_ < rhs.buckets_;
109 size_t UpperBound()
const {
return 2 * buckets_.size() + 1; }
110 size_t LowerBound()
const {
111 return std::max(HASH_SET_INITIAL_SIZE, (
static_cast<int>(buckets_.size()) - 1) / 2);
114 template <
typename T_query>
116 const size_t idx_bucket = std::hash<T_query>{}(element) % buckets_.size();
117 return buckets_[idx_bucket];
119 template <
typename T_query>
121 const size_t idx_bucket = std::hash<T_query>{}(element) % buckets_.size();
122 return buckets_[idx_bucket];
125 void Rehash(
size_t num_buckets) {
126 if (num_buckets == buckets_.size())
return;
129 std::vector<UniqueVector<T>> old_buckets(num_buckets);
130 std::swap(buckets_, old_buckets);
135 for (T& element : bucket) {
136 GetBucket(element).insert(std::move(element));
141 std::vector<UniqueVector<T>> buckets_;
148 using iterator_category = std::bidirectional_iterator_tag;
149 using value_type = T;
150 using difference_type = ptrdiff_t;
151 using pointer =
const T*;
152 using reference =
const T&;
156 const int idx_bucket,
const int idx_in_bucket)
157 : buckets_(&buckets),
158 idx_bucket_(idx_bucket),
159 idx_in_bucket_(idx_in_bucket) {}
174 reference operator*()
const {
175 return (*buckets_)[idx_bucket_][idx_in_bucket_];
178 pointer operator->()
const {
179 return &(*buckets_)[idx_bucket_][idx_in_bucket_];
183 return idx_bucket_ == rhs.idx_bucket_ &&
184 idx_in_bucket_ == rhs.idx_in_bucket_;
187 bool operator!=(
const const_iterator& rhs)
const {
return !(*
this == rhs); }
192 FindPreviousElement();
205 void FindNextElement() {
207 if (idx_bucket_ >= buckets_->size()) {
212 while (idx_in_bucket_ >= bucket->size()) {
215 if (idx_bucket_ == buckets_->size())
return;
216 bucket = &(*buckets_)[idx_bucket_];
219 void FindPreviousElement() {
221 while (idx_in_bucket_ < 0) {
223 if (idx_bucket_ < 0)
return;
225 idx_in_bucket_ = bucket.size() - 1;
229 const std::vector<UniqueVector<T>>* buckets_ =
nullptr;
231 int idx_in_bucket_ = 0;
236 using iterator_category = std::bidirectional_iterator_tag;
237 using value_type = T;
238 using difference_type = ptrdiff_t;
240 using reference = T&;
244 const int idx_in_bucket)
245 : buckets_(&buckets),
246 idx_bucket_(idx_bucket),
247 idx_in_bucket_(idx_in_bucket) {}
262 reference operator*()
const {
263 return (*buckets_)[idx_bucket_][idx_in_bucket_];
266 pointer operator->()
const {
267 return &(*buckets_)[idx_bucket_][idx_in_bucket_];
270 bool operator==(
const iterator& rhs)
const {
271 return idx_bucket_ == rhs.idx_bucket_ &&
272 idx_in_bucket_ == rhs.idx_in_bucket_;
275 bool operator!=(
const iterator& rhs)
const {
return !(*
this == rhs); }
280 FindPreviousElement();
293 void FindNextElement() {
295 if (idx_bucket_ >= buckets_->size()) {
300 while (idx_in_bucket_ >= bucket->size()) {
303 if (idx_bucket_ == buckets_->size())
return;
304 bucket = &(*buckets_)[idx_bucket_];
308 void FindPreviousElement() {
310 while (idx_in_bucket_ < 0) {
312 if (idx_bucket_ < 0)
return;
314 idx_in_bucket_ = bucket.size() - 1;
318 std::vector<UniqueVector<T>>* buckets_ =
nullptr;
320 int idx_in_bucket_ = 0;
326 #endif // SYMBOLIC_UTILS_HASH_SET_H_