C++ コンテナ - コレクション (unowned_set)

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

おすすめ

転載: blog.csdn.net/shouhu010/article/details/129795460