代码随想录算法训练营第6天 | 哈希算法理论基础

作者使用语言C++

参考文献:代码随想录 (programmercarl.com)

哈希表理论基础:

哈希表(一些算法书籍翻译为散列表)是一种以「key-value」形式存储数据的数据结构,任意的键值 key 都唯一对应到内存中的某个位置。只需要输入查找的键值,就可以快速地找到其对应的 value。举个简单的例子:数组其实就是一种哈希表,通过输入数组的下标而找到对应的数据;

常见的三种哈希结构:

分别为  :数组              set            map

数组比较简单,下面我们来重点讲解这俩种哈希结构:set和map

哈希结构 set:

set集合常见的有三种
名称底层实现是否有序可否更改数值查询效率增删效率
std::set 红黑树有序O(log n)O(log n)
std::multiset 红黑树有序O(log n)O(log n)
std::unordered_set哈希表无序O(1)O(1)

红黑树是什么?

红黑树是一种自平衡的二叉搜索树,它在每个节点上都增加了一个存储位来表示该节点的颜色,可以是红色或黑色。红黑树具有以下特性:

1. 每个节点要么是红色,要么是黑色。
2. 根节点是黑色。
3. 每个叶子节点(NIL节点,空节点)是黑色。
4. 如果一个节点是红色,则它的两个子节点都是黑色。
5. 对于每个节点,从该节点到其所有后代叶子节点的简单路径上,均包含相同数目的黑色节点。

这些特性保证了红黑树的平衡性,使其在插入、删除等操作时能够自动调整节点的位置以保持平衡。红黑树在很多编程语言的标准库中被广泛使用,因为它可以在O(log n)的时间复杂度内进行插入、删除和查找等操作。

C++中multiset是什么?

在C++中,`std::multiset`是标准库中的一个容器,它实现了一个有序的、允许重复值的集合。`std::multiset`是基于红黑树实现的,因此内部元素会按照特定的比较准则进行自动排序,并且可以包含重复的元素

与`std::set`不同的是,`std::multiset`允许存储多个相等的元素。这意味着你可以插入多个相同的值,并且在迭代器遍历时,会按照元素的顺序访问这些重复的值。

`std::multiset`提供了一系列成员函数,包括插入、删除、查找等操作,以及迭代器遍历等功能。你可以使用`std::multiset`来处理需要有序集合并允许重复值的场景,如统计频率、排序等操作。

C++中unordered_set是什么?

unordered_set是C++ STL中的一个容器,用于存储一组不重复的元素,其内部实现是基于哈希表的。unordered_set中的元素是无序的,但是可以通过哈希函数快速查找元素。

unordered_set的用法和其他STL容器类似,可以使用insert()函数向其中插入元素,使用erase()函数删除元素,使用find()函数查找元素等。另外,unordered_set还提供了一些其他的成员函数,如size()、empty()、clear()等。

unordered_set的定义方式如下:
#include <unordered_set>
using namespace std;

unordered_set<int> mySet; //定义一个存储int类型元素的unordered_set
在使用unordered_set时,需要注意以下几点:
  1. unordered_set中的元素必须是可哈希的,即需要定义哈希函数和相等比较函数。
  2. unordered_set中的元素是无序的不能通过下标访问元素。
  3. unordered_set中的元素不允许重复,如果插入重复元素会被忽略。
使用实例:
#include <iostream>
#include <unordered_set>
using namespace std;

int main()
{
    unordered_set<int> mySet;
    mySet.insert(1);
    mySet.insert(2);
    mySet.insert(3);
    mySet.insert(2); //插入重复元素,会被忽略

    cout << "mySet size: " << mySet.size() << endl; //输出元素个数

    if (mySet.find(2) != mySet.end()) //查找元素2
        cout << "2 is in mySet" << endl;
    else
        cout << "2 is not in mySet" << endl;

    mySet.erase(3); //删除元素3

    for (auto it = mySet.begin(); it != mySet.end(); ++it) //遍历元素
        cout << *it << " ";
    cout << endl;

    mySet.clear(); //清空元素

    cout << "mySet size: " << mySet.size() << endl; //输出元素个数

    return ;
}

 当我们要使用集合来解决哈希问题的时候,优先使用unordered_set,因为它的查询和增删效率是最优的,如果需要集合是有序的,那么就用set,如果要求不仅有序还要有重复数据的话,那么就用multiset。

 

哈希结构 map:

map的常见结构有三种:
映射底层实现是否有序数值是否可以重复能否更改数值查询效率增删效率
std::map红黑树key有序key不可重复key不可修改O(logn)O(logn)
std::multimap红黑树key有序key可重复key不可修改O(log n)O(log n)
std::unordered_map哈希表key无序key不可重复key不可修改O(1)O(1)
C++中multimap是什么?

在C++中,`std::multimap`是标准库中的一个容器,它实现了一个有序的键-值对集合,允许键值重复。`std::multimap`是基于红黑树实现的,因此内部元素会按照键的顺序进行自动排序

与`std::map`不同的是,`std::multimap`允许存储多个相同的键。这意味着你可以插入多个具有相同键的值,并且在迭代器遍历时,会按照键的顺序访问这些值。

`std::multimap`提供了一系列成员函数,包括插入、删除、查找等操作,以及迭代器遍历等功能。你可以使用`std::multimap`来处理需要有序键值对并允许重复键的场景,如存储日志、索引等操作。

C++中unordered_map是什么?

unordered_map 是 C++ 中 STL 库中的一种数据结构,它是一种哈希表,能够高效地存储键-值对。使用 unordered_map 需要包含 <unordered_map> 头文件。

例如:

#include <unordered_map>
#include <string>

int main() {
    std::unordered_map<std::string, int> myMap;
    myMap["hello"] = 1;
    myMap["world"] = 2;

    std::cout << myMap["hello"] << std::endl;  // 输出 1
    std::cout << myMap["world"] << std::endl;  // 输出 2
    return 0;
}

unordered_map 也可以使用迭代器遍历,支持常用的 STL 方法,如 find, count, size, clear 等。

pair用法

头文件:#include< utility >

1.pair 默认对first升序,当first相同时对second升序;
类模板:template <class T1, class T2> struct pair
参数:T1是第一个值的数据类型,T2是第二个值的数据类型。

功能:pair将一对值组合成一个值,这一对值可以具有不同的数据类型(T1和T2),两个值可以分别用pair的两个公有函数first和second访问。
pair实际上可以看作一个内部有两个元素的结构体,且这两个元素的类型是可以指定的

 struct pair{
     typename1 first;
     typename2 second;
 };

定义与构造:

pair<int, double> p1;  //使用默认构造函数
p1.first = 1;
p1.second = 2.5;
cout << p1.first << ' ' << p1.second << endl;

赋值:

//(1)利用make_pair:
pair<int, double> p1;
p1 = make_pair(1, 1.2);
//(2)变量间赋值:
pair<int, double> p1(1, 1.2);
pair<int, double> p2 = p1;

关于pair的相关操作参考文献于 https://blog.csdn.net/LUSH_BOY/article/details/113483998

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值