HashTable
Hash表实现(拉链和分散地址)
Hash策略常见的有哪些?
STL中hash_map扩容发生什么?
(1) 创建一个新桶,该桶是原来桶两倍大最接近的质数(判断n是不是质数的方法:用n除2到sqrt(n)sqrt(n)范围内的数) ;
(2) 将原来桶里的数通过指针的转换,插入到新桶中(注意STL这里做的很精细,没有直接将数据从旧桶遍历拷贝数据插入到新桶,而是通过指针转换)
(3) 通过swap函数将新桶和旧桶交换,销毁新桶。
常见的散列函数(哈希函数)有:
- 取模,将关键值对哈希表的长度值取模,是一种简单快捷的哈希策略。为了使分布更均匀,也可以在平方后取余,或者多项式函数的值后取余。有一种称为Horner法则的方法。
- 随机数法,H(Key) = random(Key),通过随机函数生成随机数进行取模。
- 相乘取整法,该方法包括两个步骤:首先用关键字key乘上某个常数A ,并抽取出key.A的小数部分;然后用m乘以该小数后取整。即:H(key) = m * (Key - Key * A)。该方法最大的优点是m的选取比除余法要求更低。比如,完全可选择它是2的整数次幂。虽然该方法对任何A的值都适用,但对某些值效果会更好。Knuth建议选取A=sqrt(5) - 1。
- 哈希函数在密码学中的应用常见的哈希函数有MD5和SHA-1。能将任意长度的字符串生成同样长度的数值。
解决冲突
解决冲突的方法有拉链法和分离地址法两种。
拉链法
就是将所有映射到同一个哈希表格的元素用一个链表保存下来,对于每个哈希表的表格都维护一张链表,有新的数据插入就在链表插入。
链表过长怎么办??
1. 红黑树
红黑树是平衡二叉树的一种,增删改查的时间复杂度是O(logn)基本。如果是传统的平衡二叉树,为了保证平衡性(左右子树高度相差不超过一),左旋右旋的调整时间花销会比较大,所以就引入的红黑树,制定新的限制规则去保证平衡性,达到调整的时间开销与查找的时间开销可以达到一个好的平衡状态。
如果但数据量很大的时候,哪怕是引入了红黑树,查找时间是O(logn),也还是不能达到我们预期的一个效率。
2.扩容
当存入(hashmap的数据量 = 位桶数组的长度 * 加载因子 )的时候,会进行一个扩容操作。扩容的操作是这样的:(1)先开辟一个之前长度*2的长度位桶数组空间。(2)重新计算集合中的元