散列表即Hash表,是一种数据的存储结构,根据元素的关键字直接计算出该元素的存储地址,优点是检索,增加删除速度都很快,缺点是散列函数 的功能不好可能会出现冲突,解决冲突会增加时间空间的开销。
最简单的散列表为直接寻址表,在当关键字的全域比较小时,直接寻址是一种简单有效的技术
散列表中存放实际元素的位置被称为槽,每个槽可谓具体元素,抑或为NIL。
散列函数,一个好的散列函数应该近似的满足简单均匀散列的假设:每个关键字都被等可能的散列到m个槽位的任何一个,并且与其他关键字散列到哪个槽位无关。
将关键字转化为自然数,多数散列函数假定关键字的全域为自然数集,当关键字为字符而非自然数时,可以通过ascii转为自然数。
散列函数有:1.除法散列法
2.乘法散列法
3.全域散列法
由于散列函数h为一压缩映像,一般来说将全域U压缩为某一有限区间[1,m],两关键字k可能会发生冲突。解决冲突的方法有两种:
1.链接法。两个关键字同时映射到某一槽,该槽中元素为指向外部一个链表的指针,发生冲突的元素存储在这一链表中
2.开放寻址法。散列函数h不仅只与关键字有关,还和一变量n有关,n为发生碰撞的次数[0,m-1],散列函数可以写为h(k,n)某一关键字映射的槽已经存在元素,则n++,h(k,n),再选取下位置
这里散列函数h(k,n) n=0....m-1 对所有的k理论上应该对于m!个序列。实际上应该尽可能的对应尽可能多的序列。有三种方法。
( 1)线性探查
( 2 ) 二次探查
( 3 ) 双重散列
对于开放寻址法的查找时,当查找的槽为NIL时,就不需要继续查找下一个槽,已经说明查找失败了。
这就遇到一个问题,当删除一个元素时,不能直接置存放该元素的槽为NIL,这会导致下一个槽中可能还有元素,但是将不再会继续检索下去。所以一般的解决方法,就是把这个槽置为另一个特殊值比如说Delete,在插入时可把Delete标记的槽视作NIL,查找时跳过即可。