C++模拟实现unordered_map和unordered_set

目录

1.了解哈希表

1.哈希表

[1.他的实现原理就是: ​编辑](#1.他的实现原理就是: 编辑)

2.写单个数据的类型(这边先模拟map的kv类型,后面会再一起改,这边先一步步的先简单实现他)

3.封装整个类:

4.哈希表中存储string

2.哈希桶

3.封装unordered中的哈希桶

4.迭代器的实现

5.封装unordered_map和unordered_set


1.了解哈希表

其实了解这两个库,就知道底层其实是一个哈希表的一个功能。所以我们首先要了解哈希表。

他其实就是解决在一堆数据里,取寻找某一个数据在不在的一个问题。想想如果让他先排序,然后在找,排序的时间复杂度其实很大了,那有没有办法用o(N)的时间复杂度将这个数据拷贝下来,在以后查找这个数据在不在,时间复杂度都是在0(1)呢?

其实这个就是哈希实现的功能。

1.哈希表

1.他的实现原理就是:

注意看这个18这个数字是不是和2这个位置冲突了,所以我们需要往后面移一个位置,那我们找也一样,也是要往后找,那找到什么时候结束?(就是找到空格结束,还没有找到就是没有;或则最坏的结果就是把这个数组都找完,因为这个数组都填满了这个数据,但是这个情况不会发生,因为我们在写这个底层是,会不断的给他扩容。你想想看,如果都快填满了,那查找它的效率就会明显下降,那就失去了他高效功能的意义了)

2.写单个数据的类型(这边先模拟map的kv类型,后面会再一起改,这边先一步步的先简单实现他)

我上面讲的数组除了存储它的数据,但我举一个例子:

如果我们删除6,再去寻找44就找不到了,所以我们就需要一个状态值了:

所以我们就可以开始第一步了:

3.封装整个类:

先看成员变量:

现在来讲解上面HashFunc是干嘛用的,他其实是一个仿函数,为什么需要仿函数呢?你要知道我们不知道key中存的是什么数据,可以无法整除整数,那就和哈希完全不相关联,所以我们要引入这个模板,当其他人使用这个类时,想存储自定义类型也是可以的,只需要让他写一个仿函数就可以了。

最后还有一点就是扩容不能超过0.7,其实每一个库实现的都不一样,这边其实没有一个统一的划分。

4.哈希表中存储string

这个为什么要单独拿出来讲呢?因为这个会出错:因为字符串转化为整形,很有可能会重叠,所以大佬们也是想了很多办法,但也只能不断地减小误差。

各种字符串Hash函数 - clq - 博客园 (cnblogs.com)

可以去这个网站上了解一下:

我就用最高评分的那种了:

就用一个模板的特例化取解决:

2.哈希桶

能明白我的意思把,就是这个数组变成了指针数组,下面是一个链表,只有next的链表。但是库里面比我这个模拟实现还要复杂,下面挂的不是单链表,而是红黑树,其实也不是很难实现,有兴趣的可以自己实现一下:

3.封装unordered中的哈希桶

这是单个数据的结点:

下面这个我就先连迭代器一起写进去了,还有一些知识因为在set和map模拟里面我有说过,这些基本是一样的,我就不累赘了,C++模拟实现set和map-CSDN博客

4.迭代器的实现

其实在我们模拟实现中,不应该按照我这个顺序来的,这在set和map那节也说过,这是因为我是已经模拟完了,才过来写这篇博客的。其实正确的模拟顺序是:

1.模拟实现哈希桶

2.初步封装unordered_map和unordered_set。

3.模拟实现迭代器

4.在迭代器中加入const迭代器

5.insert返回值, operator[]

6.map中的key和set不能修改的问题

如果一起直接写完,那必然很容易就会报错,那么就会让你很无从下手,甚至想放弃。

然后我们继续说迭代器。这个迭代器还是比较特殊的。

首先一点就是,我们要想清楚,我们成员变量只有一个Node* 的结点指针是否就够了,看上面那张图,如果结点指针指向了44,我们怎么跳到5?因为我们这个结点只有next,所以只能找到下一个,不能找到上一个,那执行oeprator++就不怎么好执行了,所以我们必须要再加一个成员变量,这个哈希桶的头指针。

但现在其实还有一个问题,我们下面的迭代器类需要_table, HashTable类需要iterator,这个相互牵扯的,每一个类都在在另一个类上面去实现他。所以就需要声明一个类了。

所以:

而且,迭代器中的_pht需要拜访_table,所以还要加一个友元:

最后看一下整体的:

5.封装unordered_map和unordered_set

相关推荐
_WndProc2 分钟前
C++ 日志输出
开发语言·c++·算法
薄荷故人_3 分钟前
从零开始的C++之旅——红黑树及其实现
数据结构·c++
m0_748240023 分钟前
Chromium 中chrome.webRequest扩展接口定义c++
网络·c++·chrome
qq_4335545411 分钟前
C++ 面向对象编程:+号运算符重载,左移运算符重载
开发语言·c++
努力学习编程的伍大侠15 分钟前
基础排序算法
数据结构·c++·算法
yuyanjingtao1 小时前
CCF-GESP 等级考试 2023年9月认证C++四级真题解析
c++·青少年编程·gesp·csp-j/s·编程等级考试
闻缺陷则喜何志丹1 小时前
【C++动态规划 图论】3243. 新增道路查询后的最短距离 I|1567
c++·算法·动态规划·力扣·图论·最短路·路径
charlie1145141911 小时前
C++ STL CookBook
开发语言·c++·stl·c++20
小林熬夜学编程2 小时前
【Linux网络编程】第十四弹---构建功能丰富的HTTP服务器:从状态码处理到服务函数扩展
linux·运维·服务器·c语言·网络·c++·http
倔强的石头1062 小时前
【C++指南】类和对象(九):内部类
开发语言·c++