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

相关推荐
C++忠实粉丝9 分钟前
计算机网络socket编程(3)_UDP网络编程实现简单聊天室
linux·网络·c++·网络协议·计算机网络·udp
我们的五年34 分钟前
【Linux课程学习】:进程描述---PCB(Process Control Block)
linux·运维·c++
程序猿阿伟1 小时前
《C++ 实现区块链:区块时间戳的存储与验证机制解析》
开发语言·c++·区块链
爱摸鱼的孔乙己1 小时前
【数据结构】链表(leetcode)
c语言·数据结构·c++·链表·csdn
烦躁的大鼻嘎2 小时前
模拟算法实例讲解:从理论到实践的编程之旅
数据结构·c++·算法·leetcode
IU宝2 小时前
C/C++内存管理
java·c语言·c++
fhvyxyci2 小时前
【C++之STL】摸清 string 的模拟实现(下)
开发语言·c++·string
C++忠实粉丝2 小时前
计算机网络socket编程(4)_TCP socket API 详解
网络·数据结构·c++·网络协议·tcp/ip·计算机网络·算法
古月居GYH2 小时前
在C++上实现反射用法
java·开发语言·c++
Betty’s Sweet2 小时前
[C++]:IO流
c++·文件·fstream·sstream·iostream