😇 😇hello!我是bug。今天我们来讲讲unordered_map和unordered_set的相关内容:
(代码可能会有一点问题,请各位老铁指正 😘 😘 )
前言
🍉 🍉unordered_map和 unordered_set是一种专门用来进行搜索的容器或者数据结构,因为其底层是哈希表,所以其增删查改的时间复杂度都是O(1),其效率是很高的。注意:这里我们哈希表用的是拉链法,即数组里面存的是单链表的首元素指针,所以无法实现自减的重载,即哈希表不提供反向迭代器。
一、unordered_map
🌳 🌳区别:
🌱 unordered_map和map的功能类似,都是KV模型。
🌱 底层不同,map的底层是红黑树,unordered_map的底层是哈希表。
🌱 map有排序的功能,而unordered_map是无序的。
🌱 从效率上看,unordered_map增删查改的时间复杂度为O(1),而map增删查改的时间复杂度为O(logN)。
🌱 从空间上看,unordered_map消耗的空间比map空间更大。
🌱 使用场景:对数据有排序或者空间要求时,选择map;对效率有要求时,选择unordered_map。
🌵🌵 unordered_map的相关接口:
函数 | 用法 |
---|---|
operator= | 重载= |
begin | 返回第一个元素的iterator |
end | 返回最后一个元素下一个位置的iterator |
empty | 判空 |
size | 返回元素个数 |
operator[] | 通过重载[]进行插入、修改 |
insert | 插入键对值 |
erase | 删除元素 |
clear | 清除元素 |
find | 查找元素 |
bucket_size | 返回桶中元素的个数 |
bucket_count | 返回桶的个数 |
bucket | 返回当前元素所处的桶数 |
二、unordered_set
🌳 🌳unordered_set和set都是K模型。因为它们的底层不同,所以其本质还是哈希表和红黑树的区别,区别在上面介绍unordered_map的时候谈到,这里不用过多篇幅。
🌵🌵 unordered_set的相关接口:
函数 | 用法 |
---|---|
operator= | 重载= |
begin | 返回第一个元素的iterator |
end | 返回最后一个元素下一个位置的iterator |
empty | 判空 |
size | 返回元素个数 |
insert | 插入元素 |
erase | 删除元素 |
clear | 清除元素 |
find | 查找元素 |
bucket_size | 返回桶中元素的个数 |
bucket_count | 返回桶的个数 |
bucket | 返回当前元素所处的桶数 |
三、哈希表
🍒 🍒哈希表实现代码⬇️ ⬇️:
#pragma once
#include<iostream>
#include<vector>
#include<string>
#include<assert.h>
using std::cin;
using std::cout;
using std::endl;
using std::pair;
using std::vector;
using std::string;
using std::make_pair;
//选出key
template<class K, class V>
struct PairSelect1st
{
const K& operator()(const pair<K, V>& kv) {
return kv.first; }
};
template<class K>
struct KSelect1st
{
const K& operator()(const K& k) {
return k; }
};
//转成整型
template<class K>
struct HashFunc
{
size_t operator()(const K& val) {
return val; }
};
//模板的特化
template<>
struct HashFunc<std::string>
{
size_t operator()(const std::string& s1)
{
size_t sum = 0;
for (size_t i = 0; i < s1.size(); i++)
{
sum = sum * 131 + s1[i];
}
return sum;
}
};
//比较判断
template<class K>
struct equal_to
{
bool operator()(const K& lval, const K& rval) {
return lval == rval; }
};
template<>
//模板特化
struct equal_to<string>
{
bool operator()(const string& s1, const string& s2) {
return s1 == s2; }
};
//素数表
const int PRIMECOUNT = 28;
const size_t primeList[PRIMECOUNT] = {
53ul, 97ul, 193ul, 389ul, 769ul,
1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
1610612741ul, 3221225473ul, 4294967291ul
};
namespace OpenHash
{
template<class T>
struct HashNode
{
typedef HashNode<T> Node;
typedef HashNode<T>* pNode;
HashNode<T>* _next;
T _data;
public:
HashNode(const T& data = T())
:_next(nullptr)
, _data(data)
{
}
};
template<class K, class V, class T, class Pred, class Select1st, class HashFunc>
class HashTable;
template<class K, class V, class T, class Ref, class Ptr, class Pred, class Select1st, class HashFunc>
struct Iterator
{
typedef HashNode<T> Node;
typedef HashTable<K, V, T, Pred, Select1st, HashFunc> HashTable;
typedef Iterator<K, V, T, Ref, Ptr, Pred, Select1st, HashFunc> self;
Node* _pnode;
HashTable* _pHT;
Iterator(Node* pnode = nullptr, HashTable* pHT = nullptr) : _pnode(pnode), _pHT(pHT) {
}
Ref operator*() {
return _pnode->_data; }
const Ref operator*()const {
return _pnode->_data; }
Ptr operator->() {
return &_pnode->_data; }
const Ptr operator->()const {
return &_pnode->_data