散列表解决冲突的方式
1. 开放定址法
开放定址法就是一旦发生冲突,就去寻找下一个空的散列地址,只要散列表足够大,空的散列地址总能找到,并将记录存入。
Hi = (H(key) + di) MOD m, i=1,2,…, k(k<=m-1),其中H(key)为散列函数,m为散列表长,di为增量序列。di可有下列三种取法:
(1)di=1,2,3,…, m-1,称为线性探测再散列;
缺点:造成大量元素在相邻的散列地址上“聚集”,大大降低查找效率。
(2)di=1^2, -(1^2), 2^2, -(2^2), 3^2, …, ±(k^2),(k<=m/2),称为二次探测再散列;
优点:避免出现“堆积”问题。
缺点:不能探测到散列表上的所有单元,但至少能探测到一半单元。
(3)di=伪随机数序列,称为伪随机探测再散列。
缺点:用同样的随机种子,将得到相同的数列。
缺点:
2. 再散列函数法
Hi=RHi(key), i=1,2,…,k RHi均是不同的散列函数(比如除留余数、折叠、平方取中),在同义词产生地址冲突时就换用另一个散列函数计算散列地址,直到碰撞不再发生。
优点:不易产生“聚集”。
缺点:增加了计算时间。
3. 链地址法
将所有关键字为同义词的记录存储在一个单链表中,称这种表为同义词子表,在散列表中只存储所有同义词子表的头指针。
优点:
缺点:
②由于拉链法中各链表上的结点空间是动态申请的,故它更适合于造表前无法确定表长的情况;
③开放定址法为减少冲突,要求装填因子α较小,故当结点规模较大时会浪费很多空间。而拉链法中可取α≥1,且结点较大时,拉链法中增加的指针域可忽略不计,因此节省空间;
④在用拉链法构造的散列表中,删除结点的操作易于实现。只要简单地删去链表上相应的结点即可。而对开放地址法构造的散列表,删除结点不能简单地将被删结 点的空间置为空,否则将截断在它之后填人散列表的同义词结点的查找路径。这是因为各种开放地址法中,空地址单元(即开放地址)都是查找失败的条件。因此在 用开放地址法处理冲突的散列表上执行删除操作,只能在被删结点上做删除标记,而不能真正删除结点。
4. 公共溢出区法
为所有冲突的关键字记录建立一个公共的溢出区来存放。在查找时,对给定关键字通过散列函数计算出散列地址后,先与基本表的相应位置进行比对,如果相等,则查找成功;如果不相等,则到溢出表进行顺序查找。如果相对于基本表而言,在有冲突的数据很少的情况下,公共溢出区的结构对查找性能来说还是非常高的。