作者使用语言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时,需要注意以下几点:
- unordered_set中的元素必须是可哈希的,即需要定义哈希函数和相等比较函数。
- unordered_set中的元素是无序的,不能通过下标访问元素。
- 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