由哈希表所联想到的相关问题

来源:互联网 发布:淘宝子账号要下载什么 编辑:程序博客网 时间:2024/05/01 11:07

 由哈希表所联想到的相关问题

C++的STL中使用了散列的容器类有:map、multimap、unordered_map、unordered_multimap、set以及multi_set。

Map和Multimap 将(key/value) 一组当做元素,它们可以根据 key 的排序准则自动将元素排序,内部是由一个红黑树实现。Multimap允许重复元素,map不允许重复。


unordered_map和unordered_multimap同上,只是内部是由一个哈希表实现。

set和multi_set则不同于以上两种,不是一个字典,而是一个普通集合,但是其内部也是由一个红黑树实现。

下面首先讲一下字典,字典是由一些形如(k,v)的数对所组成的集合,其中k是关键字,v是与关键字k对应的值(反过来说也可以)。任意两个数对,其关键字都不等。但是其对应的值可以相等,也就是说存在多对一,一对一,但是不存在一对多,类似于函数的映射。其中多对一的情况就是多重字典,典型的例子有电话薄。

字典有两种表示方法,分别是跳表和散列。主要介绍散列,它用一个散列函数(哈希函数)把字典的数对映射到一个散列表(哈希表)的具体位置。

尽管理想的散列方法用在许多字典的应用中,但是还是有许多应用,因为关键字变化范围太大,使散列表没有意义或不切实际。所以考虑实际情况就有了以下概念:

1.桶和起始桶

当关键字的范围太大,不能用理想方法表示时,可以采用并不理想的散列表和散列函数:散列表位置的数量比关键字的个树少,散列函数把若干个不同的关键字映射到散列表的同一个位置。散列表的每一个位置叫一个桶,对关键字为k的数对,f(k)是起始桶;桶的数量等于散列表的长度或大小。因为散列函数可以把若干个关键字映射到同一个桶,所以桶要能够容纳多个数对。

2.除法散列函数

在多种散列函数中,最常用的是除法散列函数,它的形式如下:

f(k)=k%D

其中k是关键字,D是散列表的长度(即桶的数量),%为求模操作符。

3.冲突和溢出

假设每个桶只能存放一个数对,当两个不同的关键字所对应的起始桶相同时,就是“冲突‘’发生了。因为一个桶可以存储多个数对,因此反生碰撞也没什么了不起。只要起始桶足够大、所有对应同一个起始桶的数对都可存储在一起。如狗存储桶没有空间存储一个新数对,就是“溢出”发生了。单就冲突而言并不可怕,可怕的是它会带来溢出,除非一个桶可以容纳无限多个数对,否则插入时的溢出不是那么容易解决的问题了。当映射到散列表中任何一个桶里的关键字数量大致相等时,冲突和溢出的平均数最少。均匀散列函数就是这样的函数。

4.解决冲突的两种方法

(1)线性探查法:最简单的方法就是找打下一个最近的可用的桶,如果后面的桶都不可用,那就把散列表视为环形表,从头找起。

(2)随机探查法:在随机探查中,当溢出发生时,以随机的方式为新数对寻找插入位置(在实际应用中,用随机数生成器产生一个桶的搜索序列,然后用这个序列去确定插入位置)。

就需要查看的桶数而言,线性探查的性能不如随机探查,需要查看更多的桶数。但是运行时间不仅受查看的桶数影响。计算一个随机数比查看若干桶更需要时间,高速缓存也使运行时间更多,因此实际线性探查效率更高。

原创粉丝点击