赞
踩
哈希表
是一种常见的数据结构
,英文名是hashtable。它和红黑树
一样是用来存储数据的。我们知道红黑树查找数据的时间复杂度是
O(
l
o
g
2
N
log_2 N
log2N) ,也就是它的高度次。但是这样效率还是太低了,所以C++的专家们就创造了哈希表,哈希表的查找效率很高时间复杂度是
O(1);
为了支持O(1)的查找效率,所以哈希表的底层由数组实现,
因为数组可以支持下标访问
,我们可以一次就锁定数据所在的空间地址。了解哈希表的底层之后,我们就该思考一个问题那么我们该如何插入数据呢?
哈希表为了节省空间不造成空间浪费一般只开一个固定空间,等空间满了再进行扩容
。
我们首先假设哈希表开了10个空间。
这时我们要插入 4和6怎么插入呢?这时我们直接按下标插入就好。
这时就有个问题了,我们要插入21该怎么办呢
?我们总不能扩容吧,那样太浪费空间了,还有好多空间都还没填上数据。这时就运用到了除留余数法
。
除留余数法的计算规则:
index为数组的下标
这时我们又遇到一个问题了,我们要插入44该怎么办?
因为4下标处的数据已经被占领了,那么我们44要放哪里?这就哈希冲突问题
。
解决哈希冲突问题的方法有三种:
线性探测
二次探测
哈希桶
前面两种也称作闭散列,后面一直称作开散列
闭散列:也叫开放定址法,当发生哈希冲突时,如果哈希表未被装满,说明在哈希表中必然还有空位置,那么可以把key存放到冲突位置中的“下一个” 空位置中去。那如何寻找下一个空位置呢?
线性探测的解决方法是我们一直往后找,直到找到空位置为止。
接下来我们多插入几个冲突的值来看一下。
比如14,24,34,54。
这是我们遇到了一个问题54我们要插入在哪里呢
?数组的后面已经没有空间了,但是数组前面还有空间啊。所以我们往后找也要进行除留余数法
。
线性探测缺点:一旦发生哈希冲突,所有的冲突连在一起,容易产生数据“堆积”,即:不同关键码占据了可利用的空位置,使得寻找某关键码的位置需要许多次比较,导致搜索效率降低。
经过线性探测处理后我们明显发现一个问题,是产生冲突的数据堆积在一块。这之后插入数据冲突的概率就太大了,那么我们如何避免呢?
线性探测是依次往后找空位置,而二次探测的按冲突次数的平方往后找位置
从这里我们可以看到冲突的位置不是那么集中了。
开散列法又叫链地址法(开链法),首先对关键码集合用散列函数计算散列地址,具有相同地址的关键码归于同一子集合,每一个子集合称为一个桶,各个桶中的元素通过一个单链表链接起来,各链表的头结点存储在哈希表中。
这就是哈希桶,哈希桶的数组存的是节点的指针,所以从这可以看出没有哈希桶的实现后根本不怕哈希冲突。
哈希表的删除其实很简单,我们用哈希表数组存放结构体
时,结构体
里面有两个数据,一个是要存的数据,一个是空间的状态值
,空间就有三种状态(EMPTY(表示没有数据),DELETE(表示已经删除),EXIST(表示已经存在))
。
我们插入成功就把状态值改成EXIST,删除就直接找到对应的数据映射位置把数据该成DELETE。
因为开散列的哈希表数组存放的是指针
,所以我们要找到数据映射的位置,然后寻找数据,最后释放这个值的空间。释放前要注意这个节点后面是否还有数据,如果有先改变链接关系再释放。
哈希表的查找很简单,用数据除留余数法再用下标寻找映射位置就能找到数据。时间复杂度为O(1)。
学了之前我们知道,数组是一定有被填满的,但是我们在什么时候扩容合适呢?
这时我们就定义了一个负载因子,负载因子在[0,1]之间,当大于某个值时就扩容。
研究表明:当表的长度为质数且表装载因子a不超过0.5时,新的表项一定能够插入,而且任何一个位置都不会被探查两次。因此只要表中有一半的空位置,就不会存在表满的问题。在搜索时可以不考虑表装满的情况,但在插入时必须确保表的装载因子a不超过0.5,如果超出必须考虑增容。
当扩容时我们就会遇到一个新的问题,我们旧哈希表的数据该怎么办,因为扩容了,空间就变大了,数据映射的位置就不一样了。那么我们就要重新把数据插入到新哈希表中。
桶的个数是一定的,随着元素的不断插入,每个桶中元素的个数不断增多
,极端情况下,可能会导致一个桶中链表节点非常多
,会影响的哈希表的性能
,因此在一定条件下需要对哈希表进行增容,那该条件怎么确认呢?开散列最好的情况是:每个哈希桶中刚好挂一个节点,再继续插入元素时,每一次都会发生哈希冲突,因此,在元素个数刚好等于桶的个数时,可以给哈希表增容。
这里还有一个问题就是,我们存的的是整形数据可以直接进行取模运算,但是如果要存的数据是字符串的类型呢?
我们要怎么办?
这里就要我们自己配套实现一个仿函数,如果是int就自己实现int类型的仿函数,如果是string就自己实现string类型的仿函数。然后用仿函数去计算。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。