STL之hashtable

hash表的概述
在平衡树中已经实现了具有对数时间表现的红黑树,而哈希表则是尝试以一种具有常数时间的表现的数据结构;
哈希表主要是通过将大数映射到小数的方法进行,但是哈希函数的存在也带来了一些问题;因为hash函数的存在,hashtable总体有三种形式:线性探测,二次探测和开链法;

1)线性探测,hash函数计算出哈希值为H,当空格H已经有元素占用,那么就执行H+i,i,1,2,3等进行逐个地探测;但是这种方式在输入的数据不是完全独立的情况下,这个会造成主集团问题;
2)二次探测,hash函数计算出哈希值为H,当空格H已经有元素占用,那么就执行H+i^2,i,1,2,3等进行逐个地探测;当根据这个散列函数进行二次散列时,可以得到满足Hi=Hi-1 + (2*i - 1)%M;方便的得到下一个探测的位置;但是当输入的数据不是完全独立的情况下这个会造成次集团问题;
3)开链法,标准的STL便是使用开链法构造的哈希表容器;所以接下来详细介绍这个方法;

数据结构
类似于deque的中控组织形式,使用vector构建自己的中控组织buckets数组,通过散列函数可以得到所输入数值val应该被放在中控组织的那个空格所对应的链表中,中控组织中的每个元素是一个指向node型变量的指针node*,一般情况下,buckets数组的大小为质数(当你初始状态下需要存在50个元素时,STL会默认给你开辟一个大小为53的buckets数组),并且将每个元素的值设置为NULL。

插入元素和取出元素
hashtable的插入元素,有两种方式:insert_equal()允许重复,插入一定会成功,所以返回一个指向插入元素的迭代器,insert_unique()不允许重复,插入不一定会成功,所以返回一个pair<position,bool>;首先根据散列函数定位到桶号,然后在链表中寻找该值应该插入的位置进行插入;在查找元素时(当然这只适合于hash_map或者hash_multimap),也是同样的道理;

清除元素
每次清除一个元素,都会释放一个节点的空间,当所有元素都清楚clear之后,buckets数组中又剩下原来的NULL指针;

重整
hashtable的重整策略有点奇葩,正常来说我们认为它的负载系数应该是大于1的,但是它总是在插入元素的时候判断当前容器中的元素个数加上1,是否已经大于buckets数组的大小,如果大于的话就会找到质数数组中的下一个质数并且使用vector的调整策略实现调整大小,最后把原来的元素,从第一条链开始逐个的计算哈希值,重新进行安排;

迭代器
hashtable只支持++iter和iter++操作,而不能后退,当执行前进操作时,如果迭代器已经指向该条链表的最后一个元素,那就通过目前所指向的元素值val获得当前所在的桶号,如果该桶号并不是bucket数组的最后一个桶,则指向下一个桶的第一个元素位置;

总结:hashtable的实现是以空间换时间的方法,它总是会浪费一部分空间,因为在每次插入时,它总是判断当前的元素数加1是否大于buckets数组的大小;


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值