python的hash函数,hash表

1:产生hash函数的原因是什么?

假设我们存在一个简单的键值对结构,键-员工号,值-是否在岗。现在需要这样一个功能,输入员工号,返回该员工是否在岗,理想的方法是创建一个长度为Max(员工号)的数组,数组下标就是员工号,数组中的值用0和1对是否在岗进行区分,这样只需要O(1)的时间复杂度就可以完成操作,但是扩展性不强,存在以下问题。

  • 1.假设新进员工的员工号比Max(员工号)还要大,这就需要重新申请数组进行迁移操作。
  • 2.假设一种极端的情况,存在两个员工,员工号分别是1和100000000001,这样子的话按照先前的设计思路,是会浪费很大的存储空间的。

上面两点,第一点是因为数组的固定申请大小的属性所决定,而第二点就是引入哈希表的原因,会不会存在一个方法,让一个大员工号变小而而且没有标记,哈希函数便产生,假设此处的哈希规则是除3取模,则员工1得到的哈希值是1,员工100000000001得到的哈希值是2,这样的话按照设计思路,只需要一个大小为2的数组便可以覆盖了,这就是哈希思想。
算法中时间和空间是不能兼得的,哈希表就是一种用合理的时间消耗去减少大量空间消耗的操作,这取决于具体的功能要求。

  • 解释一下对于python的list的内存分析:python初始化的时候一般是一个空list,当添加元素的时候,内存先分配一个大小为4的内存,将1存进去,如果再次插入2, 3, 4刚好将list放满;下一步再次放入数据的话,内存会继续开辟一个新的内存空间,将原来的4个数复制过来,同时内存继续扩大到8。所以我们可以看到消耗时间的操作就是每次内存不够的新开辟和复制,这个是非常损耗时间的,这是一个大问题。所以一般会先制定大小:利用[None for i in range(n)]迭代即可。

2:那么如果有hash函数,他本质就是一种多对一的函数,如果出现多对一,就是地址冲突,所以hash函数的本质就是如何有效的解决冲突问题?

一般有—— 开放地址,再哈希法,链地址法等

  • 开放地址:意思是除了哈希函数得出的地址可用,当出现冲突的时候其他的地址也一样可用,常见的开放地址思想的方法有线性探测再散列,二次探测再散列,这些方法都是在第一选择被占用的情况下的解决方法。从发生冲突的那个单元起,按照一定的次序,从哈希表中找到一个空闲的单元。然后把发生冲突的元素存入到该单元的一种方法。开放定址法需要的表长度要大于等于所需要存放的元素。在开放定址法中解决冲突的方法有:线行探查法、平方探查法、双散列函数探查法。
  1. 线性探测再散列:即当前位置有值,那么紧接着按顺序(按线性)寻找,直到找到空闲的位置填进去。搜索的时候也是按照这种方法,先hash函数映射,找到了就结束,找不到按顺序寻找一个个与被寻找对象对比,直到找到。
  2. 二次探测再散列:即当前位置有值,那么紧接着按照 当前地址 + 1的平方找,空闲填入,有值得话按照当前地址 - 1的平房找,即倒叙从后面找(java里面就是这么实现得),其它语言可能只有正着找;如果倒着有值,紧接着按照当前地址 +/- 2的平方找,有值按照当前地址 +/- 3的平方找,直到找到空闲。
  3. 依据上述方法,可以设置三次探测,幂函数探测都行
  • 再哈希法:这个方法是按顺序规定多个哈希函数,每次查询的时候按顺序调用哈希函数,调用到第一个为空的时候返回不存在,调用到此键的时候返回其值,默认有好多hash函数。
  • 链地址法:(用的多)将所有关键字哈希值相同的记录都存在同一线性链表中,实现得时候往往最后一个是头指针,这样不需要占用其他的哈希地址,相同的哈希值在一条链表上,按顺序遍历就可以找到。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值