1 はじめに
unowned_set は、一意のキー値を含む連想コンテナであり、ソートされません。追加、変更、およびクエリの時間計算量は線形であり、そのストレージ構造はハッシュ テーブルです。
ヘッダー ファイルと定義
#include <unordered_set>
template<
class Key,
class Hash = std::hash<Key>,
class KeyEqual = std::equal_to<Key>,
class Allocator = std::allocator<Key>
> class unordered_set;
2. 初期化
unowned_setの初期化方法は以下のとおりです。
/*
* @brief unordered_set
* @g++ -g unordered_set_main.cc -o d -std=c++11
* @author
* @date 2023/03/27
*/
#include <iostream>
#include <unordered_set>
#include <string>
template<typename T>
void showInfo(T& t)
{
for(const auto& au : t)
{
std::cout<<au<<" ";
}
std::cout<<std::endl;
}
int main(int argc, char* argv[])
{
std::unordered_set<std::string> un_s1;
un_s1.emplace("c++");
un_s1.emplace("c");
un_s1.insert("java");
un_s1.insert("Rust");
showInfo(un_s1);
//直接初始化
std::unordered_set<std::string> un_s2{
"student", "teacher", "boy", "girl", "class1", "class2", "score"};
showInfo(un_s2);
//拷贝初始化
std::unordered_set<std::string> un_s3 = un_s1;
showInfo(un_s3);
return 0;
}
出力
Rust java c++ c
class2 class1 teacher score girl boy student
Rust java c++ c
3.使用する
3.1 要素へのアクセス
方法 | 説明する |
---|---|
イテレータ | コレクション要素の走査 |
unowned_set は添字アクセスをサポートしていません
例
int main(int argc, char* argv[])
{
std::unordered_set<std::string> un_s1{
"student", "teacher", "boy", "girl", "class1", "class2", "score"};
auto iter = un_s1.begin();
while(iter != un_s1.end())
{
std::cout<<*iter<<" ";
iter++;
}
std::cout<<std::endl;
return 0;
}
出力
class2 class1 teacher score girl boy student
3.2 コレクションのサイズ
方法 | 説明する |
---|---|
空 | 空に設定する |
サイズ | コレクションサイズ |
max_size | 最大容量 |
クリア | unowned_set のサイズをクリアする |
スワップ | 2 つの unowned_sets の内容を交換します |
int main(int argc, char* argv[])
{
//empty size max_size clear swap
std::unordered_set<std::string> un_s1{
"student", "teacher", "boy", "girl", "class1", "class2", "score"};
showInfo(un_s1);
std::cout<<"size() is: "<<un_s1.size()<<"\n";
std::cout<<"max_size() is: "<<un_s1.max_size()<<"\n\n";
std::unordered_set<std::string> un_s2;
un_s1.swap(un_s2);
std::cout<<"[un_s1]"<<std::endl;
showInfo(un_s1);
std::cout<<"[un_s2]"<<std::endl;
showInfo(un_s2);
std::cout<<std::endl;
un_s2.clear();
if(un_s2.empty())
{
std::cout<<"empty\n";
}
else{
std::cout<<"not empty\n";
}
}
出力
class2 class1 teacher score girl boy student
size() is: 7
max_size() is: 384307168202282325
[un_s1]
[un_s2]
class2 class1 teacher score girl boy student
empty
3.3 要素の変更
方法 | 説明する |
---|---|
= | 直接割り当て |
get_allocator | メモリアロケータを返す |
入れる | 要素を挿入 |
場所 | 要素を挿入 |
埋め込みヒント | 要素を挿入するには、位置を追加する必要があります |
消す | 要素の削除 |
消去_if(C++20) | 条件付き削除。通常ラムダで使用されます。 |
抜粋(C++17) | 要素を削除すると、この値が返されることがあります。 |
マージ(C++17) | unowned_set のマージ |
例
int main(int argc, char* argv[])
{
//operator= get_allocator insert emplace emplace_hint erase extract merge
std::unordered_set<std::string> un_s1{
"c++"};
un_s1.insert("c");
un_s1.emplace("Rust");
un_s1.emplace_hint(un_s1.begin(), "golang");
showInfo(un_s1);
std::cout<<std::endl;
un_s1.erase(un_s1.begin());
std::cout<<"[erase]"<<std::endl;
showInfo(un_s1);
std::cout<<std::endl;
//extract
auto re = un_s1.extract(un_s1.begin());
showInfo(un_s1);
std::cout<<std::endl;
//merge
std::unordered_set<std::string> un_s2{
"student", "teacher", "boy", "girl"};
un_s1.merge(un_s2);
showInfo(un_s1);
showInfo(un_s2); //输出空
return 0;
}
出力
Rust c golang c++
[erase]
c golang c++
golang c++
c++ golang student boy girl teacher
3.5 要素に対する操作
バケットは内部ストレージ構造です
方法 | 説明する |
---|---|
カウント | unowned_set 内の要素の出現数をカウントします。 |
探す | 要素の検索 |
等しい範囲 | 範囲 [下限、上限] を返します。 |
バケット数 | バケットの数を返します |
max_bucket_count | 到達可能なバケットの最大数を返します。 |
バケットサイズ(n) | n 番目のバケット内の要素の数を返します。 |
バケツ | 戻り要素がどのバケットにあるか |
負荷率 | バケット内の要素の平均数を返します。 |
最大負荷係数 | 最大負荷率を返します |
リハッシュ(n) | バケットの数を n に設定します |
予備(n) | バケットの数を少なくとも n に設定します |
ハッシュ関数 | サイズ size_t の一意の値を返します。 |
key_eq | unowned_set で使用されるキー同等の比較述語を返します。 |
例1
int main(int argc, char* argv[])
{
std::unordered_set<std::string> un_s1{
"c", "Rust", "golang"};
showInfo(un_s1);
auto iter = un_s1.find("c");
std::cout<<*iter<<std::endl;
std::cout<<"count() test "<<un_s1.count("golang")<<std::endl;
//equal_range
auto equal_iter = un_s1.equal_range("Rust");
std::cout<<*equal_iter.first<<std::endl;
std::cout<<*equal_iter.second<<std::endl;
//bucket_count max_bucket_count bucket_size bucket
//桶
std::cout<<"un_s1 bucket_count() value is: "<<un_s1.bucket_count()<<std::endl; //返回当前桶的数量,从0到n-1
std::cout<<"un_s1 max_bucket_count() value is: "<<un_s1.max_bucket_count()<<"\n\n"; //返回最大桶的数量
std::cout<<"un_s1 "<<un_s1.bucket_size(1)<<"\n\n"; //返回桶1中元素的个数
for(int32_t i = 0; i<un_s1.bucket_count(); i++)
{
std::cout<<"size of "<<i<<" bucket is: "<<un_s1.bucket_size(i)<<std::endl;
}
std::cout<<std::endl;
std::cout<<"the location of Rust is: "<<un_s1.bucket("Rust")<<std::endl; //返回"Rust"在第几个桶中
return 0;
}
出力
golang Rust c
c
count() test 1
Rust
c
un_s1 bucket_count() value is: 5
un_s1 max_bucket_count() value is: 384307168202282325
un_s1 0
size of 0 bucket is: 0
size of 1 bucket is: 0
size of 2 bucket is: 1
size of 3 bucket is: 1
size of 4 bucket is: 1
the location of Rust is: 3
例 2
int main(int argc, char* argv[])
{
std::unordered_set<std::string> un_s1{
"c++", "c", "Rust", "golang", "linux", "matlab"};
showInfo(un_s1);
std::cout<<"bucket_count is: "<<un_s1.bucket_count()<<std::endl;
std::cout<<"un_s1.size is: "<<un_s1.size()<<std::endl;
//load_factor,返回桶的平均元素数 size()/bucket_count()
std::cout<<"load_factor value is: "<<un_s1.load_factor()<<std::endl;
//max_load_factor,返回最大负载系数
std::cout<<"max_load_factor value is: "<<un_s1.max_load_factor()<<std::endl;
//rehash,设定桶的数目
un_s1.rehash(10);
std::cout<<"bucket_count after rehash is: "<<un_s1.bucket_count()<<std::endl;
//reserve,设置桶的数目(最少包含20个)
un_s1.reserve(20);
std::cout<<"bucket_count after reserve is: "<<un_s1.bucket_count()<<std::endl;
//hash_function,返回一个唯一的大小为size_t的值
auto au_hash = un_s1.hash_function();
std::cout<<au_hash("c")<<std::endl;
//key_eq,返回unordered_set使用的键等效项比较谓词
auto au_key = un_s1.key_eq()("c","c");
if(au_key)
{
std::cout<<"equal"<<std::endl;
}
else{
std::cout<<"not equal"<<std::endl;
}
return 0;
}
出力
matlab Rust linux golang c c++
bucket_count is: 7
un_s1.size is: 6
load_factor value is: 0.857143
max_load_factor value is: 1
bucket_count after rehash is: 11
bucket_count after reserve is: 23
10959529184379665549
equal
3.6 イテレータ
迭代器最好结合STL中的算法一起使用;迭代器的返回值最好用auto接收;
迭代器的类型包括:iterator和const_iterator
方法 | 说明 |
---|---|
begin | 返回unordered_set的头元素(迭代器),其值可修改 |
end | 返回unordered_set的尾元素(迭代器),其值可修改 |
cbegin | 返回set的头元素(迭代器),其值不可修改,const属性 |
cend | 返回set的尾元素(迭代器),其值不可修改,const属性 |
迭代器的辅助函数
辅助函数的使用需要包含头文件
#include <iterator>
方法 | 说明 |
---|---|
advance | 移动迭代器的位置 |
distance | 计算两个迭代器的距离 |
begin | 返回容器第一个元素的迭代器 |
end | 返回容器最后一个元素的迭代器 |
prev | 迭代器向前移动一个元素 |
next | 迭代器向后移动一个元素 |
示例
int main(int argc, char* argv[])
{
std::unordered_set<std::string> un_s1{
"c++", "c", "Rust", "golang", "linux", "matlab"};
showInfo(un_s1);
std::cout<<std::endl;
auto au = un_s1.begin();
while (au != un_s1.end())
{
std::cout<<*au<<" ";
au++;
}
std::cout<<std::endl;
auto au_begin = un_s1.begin();
std::advance(au_begin,2);
std::cout<<*au_begin<<std::endl;
au_begin = un_s1.begin();
auto au_end = un_s1.end();
std::cout<<std::distance(au_begin,au_end)<<std::endl;
return 0;
}
输出
matlab Rust linux golang c c++
matlab Rust linux golang c c++
linux
6