【绝对有用】C++ 哈希 std::unordered_map 和 std::unordered_set

**在 C++ 中,可以使用标准库中的 std::unordered_mapstd::unordered_set 来实现哈希表。这些容器提供了快速的插入、删除和查找操作。以下是一些简单的示例代码,展示如何使用这两个容器。**

使用 std::unordered_map

std::unordered_map 是一个键值对容器,其中每个键都是唯一的。

#include <iostream>
#include <unordered_map>
#include <string>

int main() {
    // 创建一个unordered_map,键类型为std::string,值类型为int
    std::unordered_map<std::string, int> hashMap;

    // 插入键值对
    hashMap["apple"] = 3;
    hashMap["banana"] = 5;
    hashMap["orange"] = 2;

    // 查找一个键对应的值
    std::string key = "banana";
    if (hashMap.find(key) != hashMap.end()) {
        std::cout << "The value for key " << key << " is " << hashMap[key] << std::endl;
    } else {
        std::cout << "Key " << key << " not found." << std::endl;
    }

    // 遍历所有的键值对
    for (const auto& pair : hashMap) {
        std::cout << "Key: " << pair.first << ", Value: " << pair.second << std::endl;
    }

    return 0;
}

使用 std::unordered_set

std::unordered_set 是一个只包含唯一键的容器,没有对应的值。

#include <iostream>
#include <unordered_set>

int main() {
    // 创建一个unordered_set,元素类型为int
    std::unordered_set<int> hashSet;

    // 插入元素
    hashSet.insert(1);
    hashSet.insert(2);
    hashSet.insert(3);

    // 查找一个元素
    int value = 2;
    if (hashSet.find(value) != hashSet.end()) {
        std::cout << "Value " << value << " found in the set." << std::endl;
    } else {
        std::cout << "Value " << value << " not found in the set." << std::endl;
    }

    // 遍历所有的元素
    for (const int& elem : hashSet) {
        std::cout << "Element: " << elem << std::endl;
    }

    return 0;
}

选择哈希函数

默认情况下,std::unordered_mapstd::unordered_set 使用标准库中的哈希函数。如果需要自定义哈希函数,可以通过模板参数指定。例如:

#include <iostream>
#include <unordered_map>

struct CustomHash {
    std::size_t operator()(const std::pair<int, int>& p) const {
        return std::hash<int>()(p.first) ^ (std::hash<int>()(p.second) << 1);
    }
};

int main() {
    // 创建一个使用自定义哈希函数的unordered_map
    std::unordered_map<std::pair<int, int>, int, CustomHash> customHashMap;

    // 插入键值对
    customHashMap[{1, 2}] = 3;
    customHashMap[{2, 3}] = 4;

    // 查找一个键对应的值
    std::pair<int, int> key = {1, 2};
    if (customHashMap.find(key) != customHashMap.end()) {
        std::cout << "The value for key (" << key.first << ", " << key.second << ") is " << customHashMap[key] << std::endl;
    } else {
        std::cout << "Key (" << key.first << ", " << key.second << ") not found." << std::endl;
    }

    return 0;
}

**这段代码定义了一个自定义哈希函数,用于计算 std::pair<int, int> 类型的哈希值。让我们详细解释每一部分的含义。**

std::size_t operator()(const std::pair<int, int>& p) const {
    return std::hash<int>()(p.first) ^ (std::hash<int>()(p.second) << 1);
}

函数签名

std::size_t operator()(const std::pair<int, int>& p) const
  • std::size_t: 这是返回类型,通常是一个无符号整数类型,用于表示哈希值。
  • operator(): 这是一个重载的函数调用运算符,使得这个结构体对象可以像函数一样被调用。
  • const std::pair<int, int>& p: 这是函数的参数,类型为 const std::pair<int, int>&,表示传入一个 std::pair<int, int> 类型的常量引用。

函数体

return std::hash<int>()(p.first) ^ (std::hash<int>()(p.second) << 1);
  • std::hash<int>()(p.first): std::hash<int> 是标准库中的哈希函数对象,用于计算 int 类型的哈希值。std::hash<int>() 创建一个临时的哈希函数对象,然后通过 operator() 调用这个对象,计算 p.first 的哈希值。
  • std::hash<int>()(p.second): 同理,这部分计算 p.second 的哈希值。
  • ^: 这是按位异或运算符,用于将两个整数按位异或。异或运算有助于混合两个哈希值,从而减少哈希冲突。
  • (std::hash<int>()(p.second) << 1): 这一部分计算 p.second 的哈希值,然后将其左移 1 位。这相当于将哈希值乘以 2,起到了散列效果,使得组合后的哈希值更加独特。

总结

这段代码通过以下步骤计算一个 std::pair<int, int> 的哈希值:

  1. 计算 p.first 的哈希值。
  2. 计算 p.second 的哈希值,并将其左移 1 位。
  3. 将上述两个哈希值按位异或,得到最终的哈希值。

这个哈希函数结合了两个整数的哈希值,通过左移和异或运算,减少了哈希冲突,提高了哈希表的性能。


**std::unordered_mapstd::unordered_set 是 C++ 标准库中的两个容器,分别用于存储键值对和唯一元素。以下是这两个容器的详细用法,包括它们的主要成员函数和一些常见操作的示例。**

std::unordered_map 用法

std::unordered_map 是一个关联容器,存储键值对,并允许通过键快速查找值。

主要成员函数
  • 构造函数

    std::unordered_map<Key, T> map;
    std::unordered_map<Key, T> map2 = { {key1, value1}, {key2, value2} };
    
  • 插入元素

    map.insert({key, value});
    map[key] = value;
    
  • 访问元素

    map[key];             // 如果键不存在,会插入默认值
    map.at(key);          // 如果键不存在,会抛出异常
    
  • 删除元素

    map.erase(key);
    map.clear();
    
  • 查找元素

    auto it = map.find(key);
    if (it != map.end()) {
        // 键存在
    }
    
  • 其他操作

    map.size();           // 返回元素数量
    map.empty();          // 检查是否为空
    
示例代码
#include <iostream>
#include <unordered_map>
#include <string>

int main() {
    std::unordered_map<std::string, int> map;

    // 插入元素
    map["apple"] = 3;
    map.insert({"banana", 5});
    
    // 访问元素
    std::cout << "Apple: " << map["apple"] << std::endl;
    try {
        std::cout << "Banana: " << map.at("banana") << std::endl;
    } catch (const std::out_of_range& e) {
        std::cout << "Key not found: " << e.what() << std::endl;
    }

    // 查找元素
    if (map.find("orange") == map.end()) {
        std::cout << "Orange not found" << std::endl;
    }

    // 遍历元素
    for (const auto& pair : map) {
        std::cout << "Key: " << pair.first << ", Value: " << pair.second << std::endl;
    }

    // 删除元素
    map.erase("banana");
    map.clear();

    return 0;
}

std::unordered_set 用法

std::unordered_set 是一个集合容器,存储唯一元素。

主要成员函数
  • 构造函数

    std::unordered_set<T> set;
    std::unordered_set<T> set2 = { value1, value2, value3 };
    
  • 插入元素

    set.insert(value);
    
  • 删除元素

    set.erase(value);
    set.clear();
    
  • 查找元素

    auto it = set.find(value);
    if (it != set.end()) {
        // 元素存在
    }
    
  • 其他操作

    set.size();           // 返回元素数量
    set.empty();          // 检查是否为空
    
示例代码
#include <iostream>
#include <unordered_set>

int main() {
    std::unordered_set<int> set;

    // 插入元素
    set.insert(1);
    set.insert(2);
    set.insert(3);

    // 查找元素
    if (set.find(2) != set.end()) {
        std::cout << "2 found in the set" << std::endl;
    } else {
        std::cout << "2 not found in the set" << std::endl;
    }

    // 遍历元素
    for (const auto& elem : set) {
        std::cout << "Element: " << elem << std::endl;
    }

    // 删除元素
    set.erase(2);
    set.clear();

    return 0;
}

在 C++ 中,std::unordered_mapfind方法返回一个指向元素的迭代器,该迭代器指向包含指定键的键值对。如果你想通过迭代器来访问键值对,可以使用迭代器的->first->second 成员来分别访问键和值。

以下是一个详细的示例,展示如何使用 std::unordered_map::find 来获取键值对,并访问其中的键和值:

#include <iostream>
#include <unordered_map>
#include <string>

int main() {
    // 创建一个unordered_map,键类型为std::string,值类型为int
    std::unordered_map<std::string, int> map;

    // 插入一些键值对
    map["apple"] = 3;
    map["banana"] = 5;
    map["orange"] = 2;

    // 查找一个键对应的值
    std::string key = "banana";
    auto it = map.find(key);
    if (it != map.end()) {
        // 迭代器指向的键值对存在,可以通过it->first获取键,通过it->second获取值
        std::cout << "Key: " << it->first << ", Value: " << it->second << std::endl;
    } else {
        std::cout << "Key " << key << " not found." << std::endl;
    }

    // 遍历所有的键值对
    for (auto it = map.begin(); it != map.end(); ++it) {
        std::cout << "Key: " << it->first << ", Value: " << it->second << std::endl;
    }

    return 0;
}

详细解释

  1. 插入键值对

    map["apple"] = 3;
    map["banana"] = 5;
    map["orange"] = 2;
    

    使用下标运算符插入一些键值对。

  2. 查找键并获取值

    std::string key = "banana";
    auto it = map.find(key);
    

    使用 find 方法查找键 "banana",返回一个指向该键值对的迭代器。

  3. 访问迭代器的键和值

    if (it != map.end()) {
        std::cout << "Key: " << it->first << ", Value: " << it->second << std::endl;
    }
    

    通过 it->first 访问键,通过 it->second 访问值。

  4. 遍历所有键值对

    for (auto it = map.begin(); it != map.end(); ++it) {
        std::cout << "Key: " << it->first << ", Value: " << it->second << std::endl;
    }
    

    使用一个循环遍历 unordered_map 中的所有键值对,并通过迭代器访问每个键和值。

这种方法可以有效地查找和访问 unordered_map 中的元素,适用于需要快速查找和修改键值对的场景。

  • 18
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fighting的码农(zg)-GPT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值