数据结构与算法-哈希表链地址法完成

        散列表是实现字典操作的一种有效的数据结构,尽管在最坏情况下查找一个元素时间和链表相同。但实际应用中,散列表的性能是极好的,合理情况下,平均时间复杂度为O(1)。

typedef struct Datatype {
	int key;    
	USER_TYPE value;
}Datatype;

typedef struct HashTable {
	int times;
	Datatype data;
}HashTable;

        散列表是一个在时间和空间上做出权衡的数据结构。如果空间允许,可以把每个关键字当做数组下标;如果时间允许,不考虑时间消耗的话,顺序查找即可。散列表恰恰值介于这二者之间,散列表使用一个长度与实际存储数目成比例的数组来存储。

        常见的构造哈希函数是取余构造,就是把余数当做哈希值,除此之外还有:

int HashFunc(int key) {
//除留取余的构造哈希函数方法
	return key % HashTableSize;
}

        平方取中散列法:通过次方放大关键字,再取中间几位作为哈希值,通过次方放大关键字减少各关键字之间的碰撞。

        基数转换法:把十进制数看成其他进制,再按照这个进制转换为十进制,提取若干位作为哈希值。

        在构造散列表的时候,通过哈希函数计算哈希值,如果出现关键字不同但是哈希值相同时,就是产生哈希碰撞,需要给出解决哈希碰撞的方案。解决哈希碰撞的方法有:

          1、链地址法:把一个哈希值产生冲突关键字放进一个链表里面,某个哈希值产生冲突了,就把这个关键字放到这个哈希值槽的链表里面。Java中的HashMap就是这样解决冲突的,不过现在一旦同一个哈希值冲突超过7个还是8个就会把链表转换为红黑树,查找的时候效率更高。

           2、开放寻址法:大体的思想是一旦产生哈希碰撞,接着找一下空的哈希槽位,直到找到合适的位置,其中方法包括:线性探查,二次探查、伪随机探查。

            线性探查就沿着产生冲突的位置接着找它紧挨着下一个,直到不冲突了。

            二次探查看上去像在冲突的位置左右跳跃的找不冲突的位置。

            伪随机探查:建立一个随机数发生器,并给定一个随机数作为起始点,在冲突的位置借助这个随机数发生器生成随机数,去探查下一个合适的位置。

        3、完全散列(算法导论156页):我的理解是散列的散列来解决冲突,不用链表也不用线性再探测找一个不冲突的位置。每一个哈希桶里面放的还是一个散列表,第一次算出在外层哪个哈希桶里面,接着计算在这个哈希桶的散列的第几个。重点就砸要保证第二次的散列计算不产生冲突,书里面写了一堆证明,生日悖论、马尔科夫啥的,我没看懂。这种二级散列可以用指针数组做到,数组(一级散列表)中每一个指针指向一个一维数组(二级散列表)

      

  • 10
    点赞
  • 58
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值