Board logo

标题: 浅谈散列(2) [打印本页]

作者: yuyang911220    时间: 2016-8-9 22:08     标题: 浅谈散列(2)

开放寻址(openaddressing)
同链接法一样,开放寻址是一种用于解决碰撞的策略。与链接法不同的是,开放寻址将所有待散列的元素全都存放在一个散列表之中,更详细的说,使得某个关键字被散列函数作用之后得到与其对应的槽的过程称为寻址,在链接法中,每个关键字只能对应某个固定的槽,并且被散列之后该关键字将存放在与该槽对应的链表中,因此我们又可以形象地称链接法为固定寻址或封闭寻址。而开放寻址顾名思义,即每个关键字可以与散列表中的多个槽形成一对多的映射关系,因为可能在首次寻址过程中该槽已被先前的关键字所占据,因而接下来我们根据事先所制定的某个规则继续试探下一个槽是否可用,直至找到一个可用的槽并将关键字存储在其中为止。因为所有元素都存放在散列表中,因此散列表的大小必定大于或是等于原集合的大小。这里存在的一个问题是,如果仅将待散列的关键字作为函数的单个输入,那么最终必定只有与其对应的单个输出(即固定的下标值),因此我们必须寻找一个引导因子,使得在关键字不变的情况下诱使函数的输出发生变化,因为所有的关键字放在一个散列表中,因而将该引导因子的值域设置为与散列表的大小相同能够更充分的利用整个散列表,形式化地:
   设原集合中存在元素elem,诱导因子为i,散列表的大小为m,则有
    hash: (elem, i)→γ,其中i,γ∈{0,1,2,…,m-1}
    并且该函数所形成的探查序列为 <hash(elem,0),hash(elem,1), …, hash(elem,m-1)>

这里诱导因子被形式化地定义为区间[0,m)中的某个值,诱导因子i的取值序列被固定为<0,1,…,m-1>只是为了方便散列函数的实现,实际可根据原集合中的元素所存在的模式制定更具针对性的值域及取值序列,这里我们将重点放在开放寻址下的散列函数设计上。通常在开放寻址中所用的散列函数主要由以下几种:

最后要注意的一点是,因为开放寻址将所有的关键字均存放在散列表中,因此我们必须保证散列表的大小始终大于原集合的元素个数,以使得任何时刻都能将元素存放在其中,但动态集合的插入操作有可能使得散列表被填满,这种情况下如果还需进行插入操作,那么我们就必须扩大散列表,由于散列表的大小m发生变化,考虑到m是散列函数中的参数,我们并不能保证m发生变化之后,同样一个关键字能被散列至同样的槽中,因此存放在原先散列表中的关键字必须被重新散列,这就带来了额外的开销。因此我们首先应充分挖掘待存储的数据集的特点,比如作用在该集合上的操作是否在大多数情况下为搜索,而动态的插入/删除操作较少发生,或者是预留一个较大的散列表,能够保证原集合必定不超过该散列表的大小,在这之后才考虑使用开放寻址。




欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0