• 【C++】unordered_set和unordered_map介绍及使用【附OJ题】


    目录

    一、unordered_set和unordered_map的介绍和使用 

    1、介绍

     2、使用及与set和map的区别

    3、O(logN)和 O(1)的效率对比 

    二、力扣OJ题

    1、重复N次的元素

    2、两个数组的交集


    一、unordered_set和unordered_map的介绍和使用 

    1、介绍

     unordered_setunordered_mapc++11才引入的 

    unordered_set 和unordered_map不支持修改(这一点和set和map一样,本质是key值不允许修改),不然底层哈希结构就乱了,且对于数据不会自动排序,并且他不支持双向迭代器,其是单向迭代器

    命名风格来看,JAVA中的unordered_set称为HashSetset称为TreeSetunordered_map称为HashMapmap称为TreeMap,因为一个底层是哈希表实现的,一个是红黑树实现的


     2、使用及与set和map的区别

    使用下 unordered_setunordered_map,并对比setmap

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. using namespace std;
    8. void test_unordered_set_map()
    9. {
    10. cout << "测试unordered_set:" << endl;
    11. //unordered_set能去重,但不能排序
    12. unordered_set<int> us;
    13. us.insert(4);
    14. us.insert(2);
    15. us.insert(1);
    16. us.insert(5);
    17. us.insert(6);
    18. us.insert(2);
    19. //unordered_set的迭代器遍历
    20. unordered_set<int>::iterator it = us.begin();
    21. while (it != us.end())
    22. {
    23. //*it = 4;//报错,因为不能修改
    24. cout << *it << " "; // 4 2 1 5 6
    25. ++it;
    26. }
    27. cout << endl;
    28. cout << "测试set:" << endl;
    29. //set能去重,也能排序
    30. set<int> s;
    31. s.insert(4);
    32. s.insert(2);
    33. s.insert(1);
    34. s.insert(5);
    35. s.insert(6);
    36. s.insert(2);
    37. //set的迭代器遍历
    38. set<int>::iterator sit = s.begin();
    39. while (sit != s.end())
    40. {
    41. cout << *sit << " "; //1 2 4 5 6
    42. ++sit;
    43. }
    44. cout << endl;
    45. cout << "测试unordered_map" << endl;
    46. unordered_map dict;
    47. dict.insert(make_pair("sort", "排序"));
    48. dict["string"] = "字符串";//第一次operator[]相当于插入操作
    49. dict.insert(make_pair("left", "左边"));
    50. unordered_map::iterator dit = dict.begin();
    51. while (dit != dict.end())
    52. {
    53. cout << dit->first << ":" << dit->second << endl;
    54. ++dit;
    55. }
    56. cout << "测试map:" << endl;
    57. map dicts;
    58. dicts.insert(make_pair("sort", "排序"));
    59. dicts["string"] = "字符串";//第一次operator[]相当于插入操作
    60. dicts.insert(make_pair("left", "左边"));
    61. map::iterator dits = dicts.begin();
    62. while (dits != dicts.end())
    63. {
    64. cout << dits->first << ":" << dits->second << endl;
    65. ++dits;
    66. }
    67. }
    68. int main()
    69. {
    70. test_unordered_set_map();
    71. return 0;
    72. }

    运行结果如下:

    总结: 


    3、O(logN)和 O(1)的效率对比 

    注:O(1)是常数次,不是说的就是1次 

    O(logN) O(1)差别不算大,但是累计起来就有差别了,所以这也是引入unordered_setunordered_map的原因

    利用代码测试下两者的效率差异:

    1. void test_efficiency()
    2. {
    3. unordered_set<int> us;
    4. set<int> s;
    5. const int n = 1000000;
    6. vector<int> v;
    7. v.reserve(n);//需要初始化,才用resize,resize是开空间+初始化,reserve是开空间
    8. srand((unsigned int)time(0));//设立随机数种子,使每次运行程序都产生不同的数
    9. for (size_t i = 0; i < n; ++i)
    10. {
    11. v.push_back(rand());//插入每次生成的随机数
    12. }
    13. //测试unordered_set insert
    14. size_t begin1 = clock();
    15. for (size_t i = 0; i < n; ++i)
    16. {
    17. us.insert(v[i]);
    18. }
    19. size_t end1 = clock();
    20. cout << "unordered_set insert:" << end1 - begin1 << endl;
    21. //测试set insert
    22. size_t begin2 = clock();
    23. for (size_t i = 0; i < n; ++i)
    24. {
    25. s.insert(v[i]);
    26. }
    27. size_t end2 = clock();
    28. cout << "set insert:" << end2 - begin2 << endl;
    29. //测试unordered_set find
    30. size_t begin3 = clock();
    31. for (size_t i = 0; i < n; ++i)
    32. {
    33. us.find(v[i]);
    34. }
    35. size_t end3 = clock();
    36. cout << "unordered_set find:" << end3 - begin3 << endl;
    37. //测试set find
    38. size_t begin4 = clock();
    39. for (size_t i = 0; i < n; ++i)
    40. {
    41. s.find(v[i]);
    42. }
    43. size_t end4 = clock();
    44. cout << "set find:" << end4 - begin4 << endl;
    45. }

    注:性能测试:要用release版本+多次测试取平均值

    运行结果【10万个数据下】:

    运行结果【100万个数据下】:

    其实实际情况下,如果我们使用的环境支持C++11unordered_set的查找效率会比set查找效率要高的 ,综合而言还是unordered_xxx的效率要高,进而说明了O(logN)和O(1)的效率差距


    二、力扣OJ题

    1、重复N次的元素

     思路:

    这跟我们之前讲过的出现水果的次数的题差不多,利用map或unordered_map就可秒杀这道题了

    1. class Solution {
    2. public:
    3. int repeatedNTimes(vector<int>& nums) {
    4. //用map或unordered_map都行
    5. unordered_map<int, int> countMap;
    6. for (auto e : nums)
    7. {
    8. countMap[e]++;//利用operator[],传入key,返回对应value再++
    9. }
    10. int N = nums.size() / 2;
    11. for (auto& kv : countMap)
    12. {
    13. if (kv.second == N)
    14. { //若出现频率为N
    15. return kv.first;//返回key值,即nums中的数据
    16. }
    17. }
    18. return -1;//若不存在,返回一个值即可
    19. }
    20. }

    2、两个数组的交集

    1. class Solution {
    2. public:
    3. vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
    4. //nums1和nums2的元素都要去重,不然最后结果可能出现重复数据
    5. //用unordered_set对nums1中的元素去重
    6. unordered_set<int> s1;
    7. for (auto e : nums1)
    8. s1.insert(e);
    9. //用unordered_set对nums2中的元素去重
    10. unordered_set<int> s2;
    11. for (auto e : nums2)
    12. s2.insert(e);
    13. //遍历s1,如果s1中某个元素在s2中出现过,即为交集
    14. vector<int> ret;
    15. for (auto e : s1)
    16. {
    17. if (s2.find(e) != s2.end())
    18. ret.push_back(e);
    19. }
    20. return ret;
    21. }
    22. };
  • 相关阅读:
    【STM32 CubeMX】移植u8g2(一次成功)
    uniapp接入萤石微信小程序插件
    LeetCode ❀ 66. 加一 / python
    PCV0.S10.0N.000,VIS插装式压力补偿器
    2023NOIP A层联测32 红楼 ~ Eastern Dream
    Apache Doris的架构讲解
    WaitTimeManagerDemo
    swift语言下SurfGen库做的爬虫是什么样的 ?
    判断语音识别结果好坏的指标——python实现
    SpringAMQP
  • 原文地址:https://blog.csdn.net/m0_74044018/article/details/133688005