C++中的哈希表(unordered_map)

std::unordered_map 是 C++ 标准库提供的哈希表实现,用于存储键-值对。以下是 std::unordered_map 的基本用法:

包含头文件

#include <unordered_map>

创建unordered_map对象

创建一个 std::unordered_map 对象,指定键和值的类型。

unordered_map<string, int> ages;

插入键值对

ages.insert(make_pair("Allen",15));
ages["Bob"] = 16;

以上两种方式可以向unordered_map插入键值对。

访问键值

cout << ages["Allen"];
cout << ages["Cindy"];

注意,如果键值不存在,如"Cindy",会在哈希表中新建一个键值对,值会初始化为默认值。int会初始化为0。

查询键值是否存在

使用find函数

if(ages.find("xxx")==ages.end()){
    cout << "Not in map";
}
else{
    cout << ages.find("xxx")->second;
}

find()函数返回一个unordered_map的迭代器,如果存在,返回指向该键值的迭代器;如果不存在,则返回ages.end()的尾部迭代器。

unordered_map的迭代器

迭代方式: std::unordered_map 中的元素是无序的,因此迭代元素的顺序是不确定的。你不能依赖迭代器按照特定的顺序遍历元素。

删除键值对

ages.erase("Bob");

遍历

for(auto item=ages.begin();item!=ages.end();item++){
    cout << item->second;
}

在C++11后的版本中可以简化成

for(auto item : ages){
    cout << item.first << " is " << item.second;
}

注意两种遍历方式中item对元素的访问方式不同。因为,在范围循环的情况下(for(auto item:ages)),item的类型是一个pair对象,pair<const Key, T>,其中 Key 是键类型(string),T 是值类型(int)。所以可以通过.first和.second直接访问pair的元素。

而在迭代器循环的情况下,item返回的是unordered_map的迭代器,迭代器类似一个指向键值对的指针,所以需要通过->方法访问元素的值。

unordered_set

是 C++ 标准库中的关联容器,它是一种集合,用于存储一组唯一的元素。与 std::set 不同,std::unordered_set 内部使用哈希表来实现,这使得元素的查找、插入和删除操作非常高效。

与unordered_map的区别在于set只保存键的值,而map保存键值对。

  1. 包含头文件: 要使用 std::unordered_set,首先需要包含正确的头文件:

    #include <unordered_set>
  2. 创建 std::unordered_set 实例: 创建一个 std::unordered_set 对象,并指定元素的类型。例如,以下是一个存储整数的 std::unordered_set

    std::unordered_set<int> numbers;
  3. 插入元素: 使用 insert 函数来插入元素到 std::unordered_set 中:

    numbers.insert(10); 
    numbers.insert(20); 
    numbers.insert(30);

    由于 std::unordered_set 存储的是唯一元素,重复的插入会被忽略。

  4. 查找元素: 使用 find 函数来查找元素是否存在:

    auto it = numbers.find(20); 
    if (it != numbers.end()) { 
        std::cout << "20 found in the set." << std::endl; 
    } 
    else { 
        std::cout << "20 not found in the set." << std::endl;
    }
  5. 删除元素: 使用 erase 函数来删除元素:

    numbers.erase(10);
  6. 遍历 std::unordered_set 使用范围循环或迭代器来遍历集合中的元素:

    使用范围循环(C++11 及以后版本):

    for (const auto& element : numbers) { std::cout << element << " "; }

    使用迭代器:

    for (auto it = numbers.begin(); it != numbers.end(); ++it) { std::cout << *it << " "; }

  7. 无序性: std::unordered_set 中的元素是无序的,它们不会按照特定顺序存储。

std::unordered_set 提供了高效的元素查找、插入和删除操作,通常在需要存储一组唯一元素且不关心元素的顺序时使用。然而,需要注意的是,键类型必须支持哈希函数,因此如果使用自定义类型作为元素,需要提供相应的哈希函数。

为什么自定义类型需要提供哈希函数

unordered_map 使用哈希表来实现数据的存储和查找。哈希表的核心思想是通过哈希函数将键映射到表中的某个位置(桶),然后在该位置查找或插入值。哈希函数的质量对哈希表的性能和正确性有重要影响。

当你使用 std::unordered_map 存储自定义结构作为键时,你需要提供一个自定义的哈希函数,以确保以下几点:

  1. 一致性: 相同的键应该始终映射到相同的桶。这是哈希表正确性的基本要求。如果不提供自定义哈希函数,C++ 标准库会使用默认的哈希函数,但这对于自定义结构可能不是合适的。

  2. 均匀性: 好的哈希函数应该使键均匀分布到桶中,以减少哈希冲突的概率。如果多个键映射到同一个桶,性能可能会受到影响。自定义哈希函数可以根据键的属性和分布特点来优化哈希映射。

  3. 快速性: 自定义哈希函数应该具有高效的计算速度,以不影响哈希表的性能。过于复杂的哈希函数可能会降低性能。

  4. 唯一性: 如果自定义结构的相等性比较不足以确定键是否相等,哈希函数可以提供额外的信息来区分不同的键。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值