私は最近、同じ問題に出くわしました。ここに私が思いついたものがあります
#include <unordered_set>
#include <iostream>
using namespace std;
int main() {
unordered_set<int> u;
int ins = 0;
for (int i=0; i<30; i++) { // something to fill the test set
ins += i;
ins %= 73;
u.insert(ins);
}
cout << "total number of buckets: " << u.bucket_count() << endl;
for(size_t b=0; b<u.bucket_count(); b++) //showing how the set looks like
if (u.bucket_size(b)) {
cout << "Bucket " << b << " contains: ";
unordered_set<int>::local_iterator lit;
for (lit = u.begin(b); lit != u.end(b);) {
cout << *lit;
if (++lit != u.end(b))
cout << ", ";
}
cout << endl;
}
cout << endl;
int r = rand() % u.bucket_count();
while (u.bucket_size(r) == 0) // finding nonempty bucket
r = (r + 1) % u.bucket_count(); // modulo is here to prevent overflow
unordered_set<int>::local_iterator lit = u.begin(r);
if (u.bucket_size(r) > 1) { // if bucket has more elements then
int r2 = rand() % u.bucket_size(r); // pick randomly from them
for (int i = 0; i < r2; i++)
lit++;
}
cout << "Randomly picked element is " << *lit << endl;
cin.ignore();
return 0;
}
再ハッシュの問題については、次のとおりです。
- セットが成長している場合、要素/バケットの比率が 1 より大きくなると、デフォルトで再ハッシュされます。したがって、私のソリューションはここでは安全です。
ただし、セットが大きくなり、その後急速に縮小する場合は、セットが空になるまで再ハッシュしないため、チェックを実行して最終的に再ハッシュすることをお勧めします。
if (u.load_factor() < 0.1) u.rehash(u.size());
これは、セットが少なくとも 10% 使用されているかどうかをチェックし、そうでない場合は再ハッシュして、セットのサイズが現在の要素数を格納するのに適切になるようにします。(通常、新しいサイズは、サイズよりも小さい 2 のべき乗に等しくなります)