赞
踩
在上一篇文章中,我们主要是简介了哈希表,下文我们来实现开放定址法的哈希表。
开放定址法主要有两种方法,一种是线性探测,一种是二次探测,本文主要针对这两种方法进行介绍。
设给出一组元素,它们的关键码为:37,25,14,36,49,68,57,11,散列表为HT[12],表的大小m = 12,假设采用Hash(x) = x % p; // (p = 11) 11是接近m的质数,就有:
Hash(37) = 4、Hash(25) = 3 、Hash(14) = 3、Hash(36) = 3、Hash(49) = 5 、Hash(68) = 2、 Hash(57) = 2、Hash(11) = 0
采用线性探查法处理冲突
如果需要加入一个元素时,使用散列函数进行计算,确定元素的桶号H0,按此桶号查看该桶,如果是所 要搜索的元素的关键码,则说明表中已有此元素,不再进行此元素的插入,否则即为冲突,再查看紧 随其后的下一个桶,如果是空桶,则搜索失败,新元素插入即可。
所以线性探测会导致一片位置冲突,在一片范围内冲突越来越多,从而导致堆积问题。
实现方法用vector作为容器,但是删除元素会变得很麻烦,这时不敢说遇到空位置就结束,因为此时查找元素是完全查找,所以我们可以给每个位置都有一个状态,状态有一为空,二存在,三删除,遇到删除不停止,遇到空可以停止。
定义为模板写成hashnode,枚举出三个状态,包含了状态和key、value,
保持size和capcity一样大。
线性探测的扩容:
负载因子可以看作数据的占用率,一定是小于1,但是不可能为1,所以我们需要考虑的是控制负载因子,用容量除以hash的size,可以把上面的数据乘0,大于7(也可以强制转化),这时需要扩容。
但是hash的增容代价很大,不能像vector一样构造复制删除,要重新哈希,映射到新的空间中。
方法:定义新的hashtable 表,resize新的空间(获取质数表中的元素),循环对每个成员调用插入函数(此时不会增容,因为前面已经resize过了),最后转换其中的tables即可。
首先映射出index位置,此时可以包装成另外一个函数。
用另外一个函数,初步是用key%_tables的size,但是我们发现无法对string或者结构体进行取模。
我们的解决方法如下:
查找和插入内部实现类似。
遇到空停止,判断如果存在并且状态为存在则找到,状态不是存在则没有找到,没有找到则向后移动,最后判断是否到底部,index再次置为0。
首先调用查找函数,查找状态为存在则删除(注意此时采用的是置状态为删除,这便是伪删除),–size,没有找到返回失败。
主要采用仿函数,通常能变成整数的元素采用最普通的版本,本文针对于我们用的最多的string进行了一个特化版本。
不用写析构函数会自己析构。
拷贝构造也是vector内部做的。
#include <vect
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。