模拟实现unordered_map和unordered_set超详解(C++)

本文深入探讨了C++中的unordered_map和unordered_set,解释了它们与map和set的区别,强调了unordered_map和unordered_set在哈希表基础上实现的高效查找特性。文章提供了unordered_map和unordered_set的模拟实现代码,并附带了测试用例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述

😇 😇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
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

今天也要写bug

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

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

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

打赏作者

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

抵扣说明:

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

余额充值