封装哈希表

本文旨在讲解哈希表的封装,我们以哈希桶的结构来进行封装unorderedmap/set。要想实现封装哈希表,我们首先得先将哈希表的结构给搭建出来,然后再根据哈希桶的结构进一步封装unorderedmap/set!

下面我们先来实现哈希桶的结构,哈希桶的结构其实就是相同映射值的在一个桶内,然后把相同的桶内的元素通过指针链接起来即可,所以我们要先实现哈希表中的结点的结构体!因为其节点类似于链表的结构,所以里面存放的是节点的指针,以及该节点存储的值!

因为我们是用自己的方式来实现哈希表并进一步封装unorderedmap/set,所以我们得用自己的命名空间来包装!下面来看一下该哈希表结点的结构实现!步骤分为两大步:1.实现哈希表。

2.利用已有的哈希表来进行封装!

一、实现哈希表!

对于哈希表么,我们首先也得实现哈希表中的结构的结构体!上面已经讲过,该结构体类型类似于一种链表,所以我们现在就开始实现一下哈希表结点的结构体!

1.哈希表结点的结构

构造函数也是同样的,直接进行值的构造即可!

采用模版,首先一开始都将存储的元素即为pair类型,最后进行封装的时候再进行修改即可!


当哈希表的结点的结构体搭建出来的时候,我们就可以搭建我们得哈希表整体的结构了,对于哈希表而言,我们需要的成员是以哈希结点指针为元素的向量vector,以及有效元素的个数!

下面来看一下哈希表中的成员!

2.哈希表中的成员变量

都是基于模版给出的,可以适用于多种类型!

当表中的成员写完之后,我们首先要都该类进行构造函数和析构函数的编写!

3.构造函数

构造函数,就是完成初始化的动作,我们只需要对我们的vector向量开辟一段空间即可完成构造函数!

4.析构函数

因为成员变量中自定义的指针类型,所以系统默认的析构函数不能完成析构,需要我们手动释放,自己来实现析构函数!实现析构函数,只需要将表中存在的结点释放,然后置空即可!

对于析构函数,我们只需要遍历表,然后将表中存在的元素进行delete掉即可!然后一个桶内的元素清空之后,然后将表进行赋空即可!下面来看一下析构函数的实现!


构造函数以及析构函数实现之后,那么我们就开始实现一些相关操作的函数!

增删查这几个常见的函数!

5.Insert函数

对与Insert函数,我们首先需要关注的是是否需要扩容!当需要扩容的话,我们无需在新建节点了,只需要将结点的指针进行修改即可!我们需要定义一个新的vector,然后用于存储旧表中的元素!我们可以采用头插法来进行对新表的插入,最后将旧表中所有的元素插入完成之后,将旧表置空,然后交换新旧表即可!!因为新表的创建是在局部内,且在栈上进行创建的,所以不用担心有内存泄漏的问题!

下面来看一下Insert函数的实现!


实现了Insert函数之后,我们可以继续实现Find函数,如果找到Find的值时,返回该节点的指针即可,否则返回nullptr;我们要做的是首先要求出对应的映射值,然后在桶内进行遍历,若桶内存在与key值相同的元素,返回该节点的指针即可!下面我们来实现一下Find函数!

6.Find函数


实现了Find函数之后,我们再来实现Erase函数,需要注意的是,我们实现Erase函数的时候,不能复用Find函数来找到该节点,因为要删除一个节点的时候,我们需要其前驱节点以及后继节点才能正确删除,断开联系!需要注意的是,如果找到了要删除的节点,我们需要判断一下是否为头删,头删与中间节点的删除是不一样的!下面来看一下Erase函数的实现!

7.Erase函数!


HashFun的引进及实现!(用于将一个类型转化为整形!)

实现了上述函数之后,我们的哈希表基本大致实现!但是当我们插入字符类型的时候我们就会发现问题所在,因为字符类型无法自动转化为整形!这时就引进了仿函数HashFun,此时我们可以利用HashFun来将各种类型转化为整形!下面我们就来介绍一下如何实现HashFun,对于整形/浮点型等等我们直接进行强转成size_t即可,因为平常我们使用string的类型较多,所以我们对于string类型直接进行模版的特化,专门针对string类型写一个HashFun;HashFun的实现也是基于模版!下面来看一下HashFun的实现!

因为我们后期要一直使用这个仿函数,我们直接将其定义成全局即可!当引进了仿函数时,我们就需要对我们之前的代码进行修改,凡是设计到求余的操作,都要用到这个函数,将key转化为size_t类型!

所以我们直接在Hashtable该类中再加一个模版参数Hash 给他一个缺省参数!修改如下:

 再给一个缺省参数即可完成!下面我们还要声明一个这样的函数hf,下面代码凡是设计到求余的操作都要用到这个函数!那么我们就对Insert来进行改造!

其他函数凡是涉及取余都是同样的,这里不再修改其他了,就是将取余套一层hf函数即可;


二、unorderedmap/set封装

至此,我们的哈希桶结构已经完成,那么下一步就开始封装我们自己unorderdmap/set,对于我们自己的unorderedmap/set而言,我们只需要添加自己的命名空间,然后就可以与库中的unorderedmap/set进行区分!

因为基于泛型编程,我们对unorderedmap/set的封装总不能写两份代码的,所以我们要实现一种格式,让二者都能使用我们得哈希桶这个结构来进行对unorderedmap/set的封装。所以我们首先要进行修改的就是我们桶中的数据类型,我们只需要桶中的数据类型进行一种改变,即可使unorderedmap/set都能调用代码,同红黑树的封装一样,我们只需要将红黑树中的第二个模版参数当成数据节点的类型即可!下面是哈

评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值