最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++中unordered_map和unordered_set的使用

 更新時(shí)間:2026年07月23日 09:46:14   作者:流星白龍  
本文主要介紹了C++中unordered_map和unordered_set的使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

1. unordered_set系列的使用

1.1 unordered_set和unordered_multiset參考文檔

參考文檔

1.2 unordered_set類的介紹

  • unordered_set的聲明如下,Key就是unordered_set底層關(guān)鍵字的類型
  • unordered_set默認(rèn)要求Key支持轉(zhuǎn)換為整形,如果不支持或者想按自己的需求走可以自行實(shí)現(xiàn)支持將Key轉(zhuǎn)成整形的仿函數(shù)傳給第二個(gè)模板參數(shù)
  • unordered_set默認(rèn)要求Key支持比較相等,如果不支持或者想按自己的需求走可以自行實(shí)現(xiàn)支持將Key比較相等的仿函數(shù)傳給第三個(gè)模板參數(shù)
  • unordered_set底層存儲(chǔ)數(shù)據(jù)的內(nèi)存是從空間配置器申請的,如果需要可以自己實(shí)現(xiàn)內(nèi)存池,傳給第四個(gè)參數(shù)。
  • 一般情況下,我們都不需要傳后三個(gè)模板參數(shù)
  • unordered_set底層是用哈希桶實(shí)現(xiàn),增刪查平均效率是 ,迭代器遍歷不再有序,為了跟set區(qū)分,所以取名unordered_set。O(1)
  • 前面部分我們已經(jīng)學(xué)習(xí)了set容器的使用,set和unordered_set的功能高度相似,只是底層結(jié)構(gòu)不同,有一些性能和使用的差異,這里我們只講他們的差異部分。
// unordered_set模板聲明:一個(gè)不保證元素順序的集合容器
template < 
    class Key,     // 鍵與值的類型(因?yàn)槭羌?,鍵就是值)
                   // 例如:unordered_set<int>, unordered_set<string>
    
    class Hash = hash<Key>,    // 哈希函數(shù)對象類型,用于計(jì)算元素的哈希值
                              // 默認(rèn)使用標(biāo)準(zhǔn)庫的hash
    
    class Pred = equal_to<Key>,    // 判斷兩個(gè)鍵是否相等的函數(shù)對象類型
                                   // 默認(rèn)使用標(biāo)準(zhǔn)庫的equal_to
    
    class Alloc = allocator<Key>   // 內(nèi)存分配器類型
                                   // 默認(rèn)使用標(biāo)準(zhǔn)分配器allocator
> 
class unordered_set;

1.3 unordered_set和set的使用差異

  • 查看文檔我們會(huì)發(fā)現(xiàn)unordered_set的支持增刪查且跟set的使用一模一樣,關(guān)于使用我們這里就不再贅述和演示了。
  • unordered_set和set的第一個(gè)差異是對key的要求不同,set要求Key支持小于比較,而unordered_set要求Key支持轉(zhuǎn)成整形且支持等于比較,要理解unordered_set的這個(gè)兩點(diǎn)要求得后續(xù)我們結(jié)合哈希表底層實(shí)現(xiàn)才能真正理解,也就是說這本質(zhì)是哈希表的要求。
  • unordered_set和set的第二個(gè)差異是迭代器的差異,set的iterator是雙向迭代器,unordered_set是單向迭代器,其次set底層是紅黑樹,紅黑樹是二叉搜索樹,走中序遍歷是有序的,所以set迭代器遍歷是有序+去重。而unordered_set底層是哈希表,迭代器遍歷是無序+去重。
  • unordered_set和set的第三個(gè)差異是性能的差異,整體而言大多數(shù)場景下,unordered_set的增刪查改更快一些,因?yàn)榧t黑樹增刪查改效率是 ,而哈希表增刪查平均效率是 ,具體可以參看下面代碼的演示的對比差異。
// 插入函數(shù):插入元素到容器
// 參數(shù):待插入的值
// 返回:pair<迭代器,bool>
//      迭代器指向插入位置或已存在元素位置
//      bool為true表示插入成功,false表示已存在
pair<iterator,bool> insert(const value_type& val);

// 刪除函數(shù):刪除指定key的元素
// 參數(shù):要?jiǎng)h除的key
// 返回:刪除的元素個(gè)數(shù)(0表示元素不存在,1表示刪除成功)
size_type erase(const key_type& k);

// 查找函數(shù):查找指定key的元素
// 參數(shù):要查找的key
// 返回:指向找到元素的迭代器,未找到返回end()
iterator find(const key_type& k);
#include<unordered_set>  // 無序集合容器
#include<unordered_map> // 無序映射容器  
#include<set>          // 有序集合容器
#include<iostream>
using namespace std;

int test_set2()
{
    const size_t N = 1000000;  // 測試數(shù)據(jù)量100萬
    unordered_set<int> us;     // 聲明無序集合
    set<int> s;                // 聲明有序集合
    vector<int> v;             // 存儲(chǔ)測試數(shù)據(jù)的vector
    v.reserve(N);              // 預(yù)留空間,避免動(dòng)態(tài)擴(kuò)容
    srand(time(0));            // 隨機(jī)種子
    
    // 生成測試數(shù)據(jù)
    for (size_t i = 0; i < N; ++i)
    {
        //v.push_back(rand());     // N較大時(shí)重復(fù)值較多
        v.push_back(rand()+i);     // 加上i使重復(fù)值較少
        //v.push_back(i);          // 完全有序無重復(fù)
    }

    // 測試set的插入性能
    size_t begin1 = clock();
    for (auto e : v)
    {
        s.insert(e);
    }
    size_t end1 = clock();
    cout << "set insert:" << end1 - begin1 << endl;

    // 測試unordered_set的插入性能
    size_t begin2 = clock();
    us.reserve(N);             // 預(yù)留空間,避免rehash
    for (auto e : v)
    {
        us.insert(e);  
    }
    size_t end2 = clock();
    cout << "unordered_set insert:" << end2 - begin2 << endl;

    // 測試set的查找性能
    int m1 = 0;                // 記錄查找成功次數(shù)
    size_t begin3 = clock();
    for (auto e : v)
    {
        auto ret = s.find(e);
        if (ret != s.end())    // 找到元素
        {
            ++m1;
        }
    }
    size_t end3 = clock();
    cout << "set find:" << end3 - begin3 << "->" << m1 << endl;

    // 測試unordered_set的查找性能
    int m2 = 0;                // 記錄查找成功次數(shù)
    size_t begin4 = clock();
    for (auto e : v)
    {
        auto ret = us.find(e);
        if (ret != us.end())   // 找到元素
        {
            ++m2;
        }
    }
    size_t end4 = clock();
    cout << "unorered_set find:" << end4 - begin4 << "->" << m2 << endl;

    // 輸出實(shí)際插入數(shù)據(jù)量(因?yàn)橛兄貜?fù)值,所以小于N)
    cout << "插入數(shù)據(jù)個(gè)數(shù):" << s.size() << endl;
    cout << "插入數(shù)據(jù)個(gè)數(shù):" << us.size() << endl << endl;

    // 測試set的刪除性能
    size_t begin5 = clock();
    for (auto e : v)
    {
        s.erase(e);
    }
    size_t end5 = clock();
    cout << "set erase:" << end5 - begin5 << endl;

    // 測試unordered_set的刪除性能
    size_t begin6 = clock();
    for (auto e : v)
    {
        us.erase(e);
    }
    size_t end6 = clock();
    cout << "unordered_set erase:" << end6 - begin6 << endl << endl;

    return 0;
}

int main()
{
    test_set2();    // 執(zhí)行性能測試
    return 0;
}

1.4 unordered_map和map的使用差異

  • 查看文檔我們會(huì)發(fā)現(xiàn)unordered_map的支持增刪查改且跟map的使用一模一樣,關(guān)于使用我們這里就不再贅述和演示了。
  • unordered_map和map的第一個(gè)差異是對key的要求不同,map要求Key支持小于比較,而unordered_map要求Key支持轉(zhuǎn)成整形且支持等于比較,要理解unordered_map的這個(gè)兩點(diǎn)要求得后續(xù)我們結(jié)合哈希表底層實(shí)現(xiàn)才能真正理解,也就是說這本質(zhì)是哈希表的要求。
  • unordered_map和map的第二個(gè)差異是迭代器的差異,map的iterator是雙向迭代器,unordered_map是單向迭代器,其次map底層是紅黑樹,紅黑樹是二叉搜索樹,走中序遍歷是有序的,所以map迭代器遍歷是Key有序+去重。而unordered_map底層是哈希表,迭代器遍歷是Key無序+去重。
  • unordered_map和map的第三個(gè)差異是性能的差異,整體而言大多數(shù)場景下,unordered_map的增刪查改更快一些,因?yàn)榧t黑樹增刪查改效率是 ,而哈希表增刪查平均效率是 ,具體可以參看下面代碼的演示的對比差異。
// 插入函數(shù)
// 參數(shù):要插入的鍵值對或元素值
// 返回:pair<迭代器,bool>組合
//      迭代器指向插入位置或已存在元素位置
//      bool表示是否插入成功(true插入成功,false表示已存在)
pair<iterator,bool> insert(const value_type& val);

// 刪除函數(shù)
// 參數(shù):要?jiǎng)h除元素的key
// 返回:實(shí)際刪除的元素個(gè)數(shù)
//      對于set/map返回0(不存在)或1(刪除成功)
size_type erase(const key_type& k);

// 查找函數(shù)
// 參數(shù):要查找的key
// 返回:指向找到元素的迭代器
//      如果沒找到返回end()迭代器
iterator find(const key_type& k);

// map中的[]運(yùn)算符重載
// 參數(shù):關(guān)鍵字key
// 返回:key對應(yīng)的value的引用
// 特點(diǎn):如果key不存在則自動(dòng)插入,value默認(rèn)初始化
mapped_type& operator[](const key_type& k);

1.5 unordered_multimap/unordered_multiset

  • unordered_multimap/unordered_multiset跟multimap/multiset功能完全類似,支持Key冗余。
  • unordered_multimap/unordered_multiset跟multimap/multiset的差異也是三個(gè)方面的差異,key的要求的差異,iterator及遍歷順序的差異,性能的差異。

1.6 UnOrderedMap.h代碼實(shí)現(xiàn)

UnOrderedMap.h

#pragma once  // 防止頭文件被重復(fù)包含
#include"HashTable.h"  // 引入哈希表的實(shí)現(xiàn)

namespace bit
{
    // unordered_map類模板,實(shí)現(xiàn)鍵值對的無序映射
    template<class K, class V>
    class unordered_map
    {
        // 仿函數(shù)類,用于從pair中提取key值
        struct MapKeyOfT
        {
            // 重載()運(yùn)算符,返回pair中的first成員(鍵值)
            const K& operator()(const pair<K, V>& kv)
            {
                return kv.first;
            }
        };

    public:
        // 使用類型別名簡化迭代器類型的書寫
        // 注意這里的模板參數(shù):
        // K: 鍵類型
        // pair<K,V>: 實(shí)際存儲(chǔ)的值類型(鍵值對)
        // MapKeyOfT: 提取鍵的仿函數(shù)
        typedef typename hash_bucket::HashTable<K, pair<K, V>, MapKeyOfT>::iterator iterator;

        // 返回容器的起始迭代器
        iterator begin()
        {
            return _ht.begin();
        }

        // 返回容器的結(jié)束迭代器
        iterator end()
        {
            return _ht.end();
        }

        // 插入鍵值對
        // 參數(shù)kv: 要插入的鍵值對
        // 返回值: 插入是否成功
        bool insert(const pair<K, V>& kv)
        {
            return _ht.Insert(kv);
        }

    private:
        // 底層哈希表對象
        // K: 鍵類型
        // pair<K,V>: 存儲(chǔ)的值類型
        // MapKeyOfT: 提取鍵的仿函數(shù)
        hash_bucket::HashTable<K, pair<K, V>, MapKeyOfT> _ht;
    };
}

1.7 UnOrderedSet.h代碼實(shí)現(xiàn)

UnOrderedSet.h

#pragma once  // 防止頭文件被重復(fù)包含
#include"HashTable.h"  // 引入哈希表的實(shí)現(xiàn)

namespace bit
{
    // unordered_set類模板,實(shí)現(xiàn)無序集合
    // 特點(diǎn):不重復(fù)、無序、只存儲(chǔ)key
    template<class K>
    class unordered_set
    {
        // 仿函數(shù)類,用于返回key值本身
        // 因?yàn)閟et只存儲(chǔ)key,所以key和value是同一個(gè)值
        struct SetKeyOfT
        {
            // 重載()運(yùn)算符,直接返回key
            const K& operator()(const K& key)
            {
                return key;
            }
        };

    public:
        // 使用類型別名簡化迭代器類型的書寫
        // 注意這里的模板參數(shù):
        // K: 鍵類型
        // K: 值類型(與鍵相同)
        // SetKeyOfT: 提取鍵的仿函數(shù)
        typedef typename hash_bucket::HashTable<K, K, SetKeyOfT>::iterator iterator;

        // 返回容器的起始迭代器
        iterator begin()
        {
            return _ht.begin();
        }

        // 返回容器的結(jié)束迭代器
        iterator end()
        {
            return _ht.end();
        }

        // 插入元素
        // 參數(shù)key: 要插入的值
        // 返回值: 插入是否成功(如果元素已存在則返回false)
        bool insert(const K& key)
        {
            return _ht.Insert(key);
        }

    private:
        // 底層哈希表對象
        // K: 鍵類型
        // K: 值類型(與鍵相同)
        // SetKeyOfT: 提取鍵的仿函數(shù)
        hash_bucket::HashTable<K, K, SetKeyOfT> _ht;
    };
}

到此這篇關(guān)于C++中unordered_map和unordered_set的使用的文章就介紹到這了,更多相關(guān)C++ unordered_map和unordered_set內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++基于字符串實(shí)現(xiàn)大數(shù)相乘問題的代碼詳解

    C++基于字符串實(shí)現(xiàn)大數(shù)相乘問題的代碼詳解

    在實(shí)際編程中,我們經(jīng)常會(huì)遇到需要處理大整數(shù)的情況,由于編程語言中內(nèi)置整數(shù)類型有其表示范圍的限制,當(dāng)需要處理的整數(shù)超出這些范圍時(shí),就不能直接使用內(nèi)置類型進(jìn)行計(jì)算,所以本文給大家介紹了相關(guān)的解決方法,需要的朋友可以參考下
    2025-03-03
  • C語言 結(jié)構(gòu)體和指針詳解及簡單示例

    C語言 結(jié)構(gòu)體和指針詳解及簡單示例

    本文主要介紹C語言 結(jié)構(gòu)體和指針,這里整理了相關(guān)資料,并附示例代碼和實(shí)現(xiàn)結(jié)果,以便大家學(xué)習(xí)參考,希望能幫助學(xué)習(xí)C語言的朋友
    2016-08-08
  • 深入理解C語言sizeof()計(jì)算空間大小為8的問題

    深入理解C語言sizeof()計(jì)算空間大小為8的問題

    本文將介紹C語言中的sizeof()函數(shù),以及如何使用它來計(jì)算變量、數(shù)據(jù)類型和數(shù)組在內(nèi)存中的大小,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-09-09
  • Linux?C/C++?timeout命令實(shí)現(xiàn)運(yùn)行具有時(shí)間限制功能

    Linux?C/C++?timeout命令實(shí)現(xiàn)運(yùn)行具有時(shí)間限制功能

    inux?timeout命令的一個(gè)屬性是時(shí)間限制。可以為任何命令設(shè)置時(shí)間限制。如果時(shí)間到期,命令將停止執(zhí)行,這篇文章主要介紹了Linux?C/C++?timeout命令實(shí)現(xiàn)(運(yùn)行具有時(shí)間限制),需要的朋友可以參考下
    2023-02-02
  • 關(guān)于線程同步與Mutex的使用

    關(guān)于線程同步與Mutex的使用

    這篇文章主要介紹了關(guān)于線程同步與Mutex的使用,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-05-05
  • MFC自定義消息的實(shí)現(xiàn)方法

    MFC自定義消息的實(shí)現(xiàn)方法

    這篇文章主要介紹了MFC自定義消息的實(shí)現(xiàn)方法,通過該示例可以更好的理解MFC的消息封裝機(jī)制,以便更加靈活的打造個(gè)性化的windows應(yīng)用程序,需要的朋友可以參考下
    2014-07-07
  • C語言鏈表實(shí)現(xiàn)工資管理系統(tǒng)

    C語言鏈表實(shí)現(xiàn)工資管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C語言鏈表實(shí)現(xiàn)工資管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • C++基類指針和派生類指針之間的轉(zhuǎn)換方法講解

    C++基類指針和派生類指針之間的轉(zhuǎn)換方法講解

    今天小編就為大家分享一篇關(guān)于C++基類指針和派生類指針之間的轉(zhuǎn)換方法講解,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-04-04
  • c++之類型別名的實(shí)現(xiàn)

    c++之類型別名的實(shí)現(xiàn)

    本文主要介紹了c++之類型別名的實(shí)現(xiàn),包括C++98版本使用typedef關(guān)鍵字和C++11版本推薦使用using關(guān)鍵字來創(chuàng)建類型別名,具有一定的參考價(jià)值,感興趣的可以了解一下
    2025-02-02
  • OpenCV?直方圖均衡化的實(shí)現(xiàn)原理解析

    OpenCV?直方圖均衡化的實(shí)現(xiàn)原理解析

    直方圖均衡化是通過拉伸像素強(qiáng)度分布范圍來增強(qiáng)圖像對比度的一種方法,今天通過本文給大家介紹OpenCV?直方圖均衡化的實(shí)現(xiàn)原理解析,感興趣的朋友跟隨小編一起看看吧
    2022-01-01

最新評論

景东| 兰西县| 绩溪县| 浦城县| 建湖县| 含山县| 漳浦县| 富顺县| 华亭县| 皮山县| 民县| 若尔盖县| 平定县| 图片| 应城市| 黔西| 密云县| 方正县| 永安市| 扎鲁特旗| 大名县| 星子县| 大悟县| 从化市| 宜兰市| 虎林市| 公主岭市| 南华县| 洛隆县| 呈贡县| 新野县| 丽水市| 汉沽区| 名山县| 营山县| 武鸣县| 肃北| 长宁县| 凉城县| 惠来县| 方正县|