代码随想录 哈希表总结 C++

哈希表

用途

        什么时候需要考虑使用哈希表呢?

        针对一个集合,我们若想快速判断一个元素是否存在于这个集合中时,就应当考虑哈希法。(如查找一个key值是否在我们想要的集合中:学生名是否在学校的名单里)哈希表查找key的时间复杂度为O(1),可以近似为随机读取。

        当使用哈希表来解决问题时,一般有三种选择:

        1.数组,如要区分一个仅包含小写字母字符串s中各字符的数目,可以使用s[i] - 'a'(ascii码的妙用),将其映射到为索引0-25的一个数组上,这种映射方式是有效且高效的。有效的字母异位词。数组,简单哈希表icon-default.png?t=N7T8https://programmercarl.com/0242.%E6%9C%89%E6%95%88%E7%9A%84%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D.html#%E6%80%9D%E8%B7%AF代码随想录 (programmercarl.com) 赎金信icon-default.png?t=N7T8https://programmercarl.com/0383.%E8%B5%8E%E9%87%91%E4%BF%A1.html#%E6%80%9D%E8%B7%AF

        2.set(集合),用于存储独一无二的元素,其中元素是无序的,查找、添加和删除操作的时间复杂度均为O(1)。它通常用于检查某个元素是否存在于集合中,或者用于去除重复元素。

代码随想录 (programmercarl.com) 两个数组的交集icon-default.png?t=N7T8https://programmercarl.com/0349.%E4%B8%A4%E4%B8%AA%E6%95%B0%E7%BB%84%E7%9A%84%E4%BA%A4%E9%9B%86.html#%E7%AE%97%E6%B3%95%E5%85%AC%E5%BC%80%E8%AF%BE代码随想录 (programmercarl.com) 快乐数icon-default.png?t=N7T8https://programmercarl.com/0202.%E5%BF%AB%E4%B9%90%E6%95%B0.html#%E6%80%9D%E8%B7%AF

        3.map(映射),map是一个键值对集合,用于存储键和值的关联,若使用哈希表实现,查找、添加和删除操作的时间复杂度为O(1)。map中元素是无序的键值对,键key是独一无二的,而value值可以重复。它通常用于根据键来快速查找、添加或删除对应的值。

        代码随想录 (programmercarl.com) 两数之和icon-default.png?t=N7T8https://programmercarl.com/0001.%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C.html#%E6%80%9D%E8%B7%AF代码随想录 (programmercarl.com)icon-default.png?t=N7T8https://programmercarl.com/0454.%E5%9B%9B%E6%95%B0%E7%9B%B8%E5%8A%A0II.html#%E7%AE%97%E6%B3%95%E5%85%AC%E5%BC%80%E8%AF%BE

实现

        在C++中,哈希表主要使用std::unordered_map和std::unordered_set这两个容器实现。

        1.std::unordered::map:

  • 关联容器,用于存储键值对,其中键是唯一的,而值可以重复。
  • 使用哈希表实现,能提供快速的查找、插入和删除操作,时间复杂度为O(1)。
  • 键的哈希值用于确定存储位置,如果发生哈希冲突,容器会使用链表或其他数据结构来处理冲突。

        2.std::unordered::set:   

  • 集合容器,用于存储唯一的元素。
  • 使用哈希表实现,因此通常提供快速的查找、插入和删除操作,时间复杂度为O(1)。
  • 元素的哈希值用于确定存储位置,处理冲突的方式与std::unordered_map类似。

        除此之外,C++还提供了其他基于哈希表的容器,如std::unordered_multimap和std::unordered_multiset,它们允许键或值有多个实例(允许键值冲突),通常底层实现为红黑树,查找、插入和删除的效率为O(logn)。 

基本操作     

unordered_map 

//创建unordered_map
std::unordered_map<int, std::string> umap = {
    {1, "one"},
    {2, "two"},
    {3, "three"}
};

//插入元素
umap.insert(std::make_pair(4, "four")); // 使用 pair
umap[5] = "five"; // 使用下标运算符


//查找元素
auto it = umap.find(2); // 返回一个迭代器,如果找到则指向元素,否则指向 end()
if (it != umap.end()) {
    std::cout << "Found: " << it->second << std::endl;
}

//访问元素
std::string value = umap[2]; // 如果键不存在,会创建一个默认构造的值
std::string value = umap.at(2); // 如果键不存在,抛出 std::out_of_range 异常

//删除元素
umap.erase(2); // 删除键为 2 的元素

//检查元素是否存在
if (umap.count(3) > 0) {
    std::cout << "Key 3 exists" << std::endl;
}


//遍历元素
for (const auto& pair : umap) {
    std::cout << pair.first << " -> " << pair.second << std::endl;
}


//获取容器大小
size_t size = umap.size(); // 返回元素的数量


//检查容器是否为空
bool empty = umap.empty(); // 如果容器为空,返回 true

//清空容器
umap.clear(); // 删除所有元素


//获取桶的数量
size_t bucket_count = umap.bucket_count(); // 返回桶的数量

//获取特定键的桶索引
size_t bucket_index = umap.bucket(2); // 返回键为 2 的元素的桶索引

在 C++ 的 std::unordered_map 中,“桶”(bucket)是用于存储具有相同或相近哈希值的关键字的内部容器。每个桶包含了一系列的元素,这些元素的哈希值在经过哈希表的哈希函数处理后,映射到了同一个桶上。

当哈希表中的元素增多时,为了保持性能,哈希表会根据需要增加桶的数量,这个过程称为重新哈希(rehashing)。重新哈希会导致所有现有的元素被重新分配到新的桶中,这是一个相对昂贵的操作。

获取桶的数量意味着查询哈希表当前有多少个这样的桶。这个信息可以用于分析哈希表的性能和效率。例如,如果一个哈希表有很多元素但桶的数量很少,可能会导致大量的哈希冲突,从而降低性能。相反,如果桶的数量远大于元素的数量,可能会浪费空间。

unordered_set

set基本与map的操作类似,但需要注意的是set只保存键

//创建unordered_set
std::unordered_set<int> uset = {1, 2, 3};

//插入元素
uset.insert(4); // 插入元素 4

//查找元素
auto it = uset.find(2); // 返回一个迭代器,如果找到则指向元素,否则指向 end()
if (it != uset.end()) {
    std::cout << "Found: " << *it << std::endl;
}

//检查元素是否存在
if (uset.count(3) > 0) {
    std::cout << "Element 3 exists" << std::endl;
}

//删除元素
uset.erase(2); // 删除元素 2

//遍历元素
for (const int& value : uset) {
    std::cout << value << std::endl;
}

//获取容器大小
size_t size = uset.size(); // 返回元素的数量

//检查容器是否为空
bool empty = uset.empty(); // 如果容器为空,返回 true

//清空容器
uset.clear(); // 删除所有元素

//获取桶的数量
size_t bucket_count = uset.bucket_count(); // 返回桶的数量

//获取特定元素的桶索引
size_t bucket_index = uset.bucket(2); // 返回元素 2 的桶索引

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值