C++ 入门第 20 天:STL 容器之无序集合与无序多重集合

往期回顾:

C++ 入门17:STL 容器之映射(map)与多重映射(multimap)_-优快云博客

C++ 入门18:STL 容器之栈(stack)与队列(queue)-优快云博客

C++ 入门19:STL 容器之优先队列(priority_queue)-优快云博客


 C++ 入门第 20 天:STL 容器之无序集合与无序多重集合

一、前言

在之前的学习中,我们已经掌握了 setmultiset 容器,它们都是有序关联容器。但在某些场景下,我们并不关心元素的顺序,而是追求更高的性能。在这种情况下,C++ 提供了 无序容器,例如 unordered_setunordered_multiset,它们的底层基于 哈希表(Hash Table) 实现,能够以常数时间完成插入、删除和查找操作。

1. 无序集合(unordered_set)

unordered_set 是一个 无序关联容器,用于存储不重复的元素。与 set 不同,unordered_set 的元素没有顺序,它的主要特点是:

  1. 底层实现:基于哈希表,操作效率高。
  2. 唯一性:不允许重复元素。
  3. 平均时间复杂度:插入、删除、查找的时间复杂度为 O(1)O(1)O(1)。

1.1 基本操作

以下是 unordered_set 的常用操作:

成员函数功能说明
insert(value)插入元素
erase(value)删除指定元素
find(value)查找元素,返回迭代器
count(value)检查某元素是否存在(返回 0 或 1)
size()获取元素个数
empty()检查容器是否为空

示例代码:基本操作 

#include <iostream>
#include <unordered_set>
using namespace std;

int main() {
    // 定义一个无序集合
    unordered_set<int> us;

    // 插入元素
    us.insert(10);
    us.insert(20);
    us.insert(30);
    us.insert(10); // 重复元素将被忽略

    // 遍历集合
    cout << "Elements in unordered_set: ";
    for (int elem : us) {
        cout << elem << " ";
    }
    cout << endl;

    // 查找元素
    if (us.find(20) != us.end()) {
        cout << "Element 20 is found in the unordered_set." << endl;
    }

    // 删除元素
    us.erase(10);
    cout << "After removing 10, elements in unordered_set: ";
    for (int elem : us) {
        cout << elem << " ";
    }
    cout << endl;

    return 0;
}

注意:输出的元素顺序与插入顺序无关,因为 unordered_set 使用哈希表存储数据。 

1.2 哈希表的特性

无序集合通过哈希函数将值映射到特定的存储位置。哈希表的效率依赖于:

  1. 哈希函数:将值映射到存储位置。
  2. 装载因子(load factor):当前元素数量与桶数量的比值。过高时,哈希表会进行重新哈希(rehash)。

我们可以通过以下函数查看或修改哈希表的状态:

成员函数功能说明
bucket_count()返回桶的数量
load_factor()返回装载因子
max_load_factor(f)设置装载因子的上限
rehash(n)强制重新哈希并至少设置 n 个桶

示例代码:查看哈希表状态

#include <iostream>
#include <unordered_set>
using namespace std;

int main() {
    unordered_set<int> us = {10, 20, 30};

    cout << "Bucket count: " << us.bucket_count() << endl;
    cout << "Load factor: " << us.load_factor() << endl;

    // 强制重新哈希
    us.rehash(20);
    cout << "After rehash, bucket count: " << us.bucket_count() << endl;

    return 0;
}

2. 无序多重集合(unordered_multiset)

unordered_multisetunordered_set 类似,不同点是:

  1. 允许重复元素:可以插入多个值相同的元素。
  2. 哈希表存储:仍然基于哈希表实现。

2.1 基本操作

unordered_multiset 的常用操作与 unordered_set 类似,但允许重复元素:

成员函数功能说明
insert(value)插入元素
erase(value)删除指定元素
count(value)返回某元素出现的次数

示例代码:无序多重集合

#include <iostream>
#include <unordered_set>
using namespace std;

int main() {
    // 定义一个无序多重集合
    unordered_multiset<int> ums;

    // 插入元素
    ums.insert(10);
    ums.insert(20);
    ums.insert(10); // 允许重复

    // 遍历集合
    cout << "Elements in unordered_multiset: ";
    for (int elem : ums) {
        cout << elem << " ";
    }
    cout << endl; // 输出:10 20 10(顺序可能不同)

    // 查询某元素的出现次数
    cout << "Count of 10: " << ums.count(10) << endl;

    // 删除某个值的所有实例
    ums.erase(10);
    cout << "After removing 10, elements in unordered_multiset: ";
    for (int elem : ums) {
        cout << elem << " ";
    }
    cout << endl;

    return 0;
}

3. unordered_setunordered_multiset 的性能分析

优点

  1. 高效:基于哈希表实现,插入、删除、查找的平均时间复杂度为 O(1)O(1)O(1)。
  2. 灵活:支持快速查找和重复值存储。

缺点

  1. 顺序无保证:无法保证元素存储顺序,适合只关心内容的场景。
  2. 哈希冲突:当冲突较多时,性能可能下降,接近 O(n)O(n)O(n)。

对比:set vs unordered_set

特性setunordered_set
底层结构红黑树哈希表
是否有序有序无序
查找时间复杂度O(log⁡n)O(\log n)O(logn)O(1)O(1)O(1)(平均情况)
插入、删除时间复杂度O(log⁡n)O(\log n)O(logn)O(1)O(1)O(1)(平均情况)

4. 实际应用场景

  • 去重unordered_set 适合需要去重但不关心顺序的场景,例如统计某一组数据中不重复的值。
  • 频率统计unordered_multiset 可以用来统计某些值的出现次数。
  • 高效查找:在大规模数据中快速查找是否存在某元素。

    示例:统计字符串中单词出现次数

    使用 unordered_multiset 来统计一个字符串中单词的频率。

    示例代码
    #include <iostream>
    #include <unordered_set>
    #include <sstream>
    #include <string>
    using namespace std;
    
    int main() {
        string text = "hello world hello C++ world";
        unordered_multiset<string> wordCount;
    
        // 将字符串分割为单词
        stringstream ss(text);
        string word;
        while (ss >> word) {
            wordCount.insert(word);
        }
    
        // 输出每个单词的出现次数
        for (const string& w : wordCount) {
            cout << w << ": " << wordCount.count(w) << endl;
            wordCount.erase(w); // 删除已处理的单词
        }
    
        return 0;
    }
    

    结语

    以上就是 C++ 标准模板库中的无序集合与无序多重集合的基础知识点了。这些无序容器通过哈希表实现,能够提供极高的操作效率,适用于需要快速查找、插入和删除的场景。掌握无序集合与无序多重集合的使用,基本上在开发中都会用到的,大家多看看,一定要掌握。

  • 都看到这里了,点个赞再走呗朋友~

  • 加油吧,预祝大家变得更强!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值