散列表.md

本文介绍了散列表的基本概念,包括散列函数的设计原则及其在不同类型数据上的应用,并详细讨论了拉链法和线性探测法两种冲突解决策略。

散列表

  • 目的:如果所有的键都是小整数,可以用一个数组来实现无序的符号表,将作为数组的索引而数组中键i处存储的就是它对应的值。
  • 查找算法步骤
    1. 散列函数将查找的函数转化为数组的一个索引。理想情况下,不同的减可以转换为不同的索引值。
    2. 处理碰撞冲突,分为拉链法线性探测法
  • 散列表是算法在时间和空间上的均衡处理方式。

散列函数

  • 散列函数特点:散列函数应该易于计算并且能够均匀分布所有的键,即对于任意的键,所给出的散列值应得呈随机性。
  • 散列函数与键的类型有关。
    1. 正整数:正整数散列最常用的方式为除留余数法。选择一个M的素数的数组,对于任意正整数k,计算k%M。如果不是素数,可能无法获得均匀的散列值。
    2. 浮点数:如果键值是0到1之间,可以将键值乘以素数M后,四舍五入得到一个0到M-1之间的索引值。但这样会使键的高位起作用更大,低位键值不影响散列值。解决办法是,键值用二进制表示后使用除留余数法
    3. 字符串:字符串散列同样使用除留余数法,将字符串考虑为大整数即可。Java的charAt()函数能够返回一个非负16位整数。如果R是比任何字符都大的整数,相当于,将字符串当做一个N位的R进制值,将它除以M求余。Horner方法,用N次乘法、加法和取余来计算一个字符串的散列值。只要R足够小,不造成溢出。
      java
      int hash = 0;
      for (int i = 0; i < s.length(); i++)
      hash = (R * hash + s.charAt(i)) % M
    4. 组合键:如果键的类型包含多个整形变量,我们可以和String类型一样将他们混合起来。例如,被查找的类型是Date,其中整型域:day(两位数)、month(两位数)和year(四位数),散列值是:
      Java
      int hash = (((day * R + month) % M) * R + year) % M;

      • 只要R足够小不造成溢出,也可以得到0到M-1之间的散列值。同时选取适当素数M值,例如31,来省去括号内的%M计算。
  • Java约定:即散列值的硬性规则。由于每种数据类型都需要相应的散列函数,于是Java让所有数据类型都继承了一个能够返回32bit整数的hashCode()方法。因此若a.equals(b)的值为ture,那么对应的hashCode值也应相同,若hashCode值不同,只能说明看似相同的数据,实则为不同数据类型。但同hashCode值,两个对象可能不同。
  • 将hashCode的返回值转化为数组索引:若我们想使用短的索引值,而不是32bit整数的散列值,这里利用hashCode()方法和除留余数法结合,产生0到M-1的整数。
  private int hash(Key x){
      return (x.hashCode() & 0x7ffffffff) % M;
  }
  • 自定义的hashCode()方法:可以按照将hashCode的返回值转化为短整数的方法,进行变换。将对象的每个变量的hashCode()返回值转化为32位整数并计算得到散列值。
public class Transaction{
    ...
    private final String who;
    private final Date when;
    private final double amount;

    public int hashCode(){
    int hash = 17;
    hash = 31 * hash + who.hashCode();
    hash = 31 * hash + when.hashCode();
    hash = 31 * hash + ((Double) amount).hashCode();
    return hash;
    }
    ...
} 
  • 软缓存:如果散列值的计算很耗时,可以将计算的散列值存储在每个键的散列值函数里,即利用hash变量存储hashCode()的返回值。

基于拉链法的散列表

基于线性探测法的散列表

<think>好的,我需要回答用户的问题:MD5是否基于哈希表或散列表实现存储?首先,我需要明确MD5和哈希表的基本概念。 根据引用[1],MD5是一种哈希算法,用于生成数据的摘要,如数字签名、文件校验等。而引用[2]和[3]提到,哈希表是一种数据结构,通过哈希函数将键映射到地址,并处理冲突。MD5属于哈希算法,而哈希表是存储结构,两者的功能不同。MD5不涉及存储数据,而是生成固定长度的哈希。因此,MD5本身并不使用哈希表进行存储,而是可能被用于哈希表中的哈希函数部分。需要确认两者的关系,避免混淆概念。</think>MD5算法**不基于哈希表或散列表实现存储**,两者属于不同层面的技术概念,具体区别如下: --- ### 一、MD5与哈希表的核心区别 1. **MD5的定位** MD5是一种**单向哈希函数**,作用是将任意长度的输入(如文件、密码)转换为固定长度(128位)的哈希。例如,字符串`"hello"`经过MD5处理后得到哈希`5d41402abc4b2a76b9719d911017c592`[^1]。其核心功能是**生成数据摘要**,而非存储数据。 2. **哈希表的定位** 哈希表是**数据结构**,通过哈希函数(如MD5、SHA-1)将键(key)映射到内存地址,并利用链地址法、开放地址法等解决冲突,最终实现数据的快速存储与检索[^2]。例如,Java的`HashMap`使用链地址法处理冲突[^2]。 --- ### 二、两者的关联与分工 - **MD5可能在哈希表中作为哈希函数** 哈希表需要哈希函数来计算键的存储位置,理论上可以使用MD5(尽管不推荐,因MD5存在安全漏洞[^1])。例如: ```python def hash_function(key): md5_hash = hashlib.md5(key.encode()).hexdigest() return int(md5_hash, 16) % table_size # 将MD5结果映射到哈希表地址 ``` 但实际更常用简单高效的哈希函数(如取模运算)。 - **MD5不参与存储管理** MD5仅生成哈希,而哈希表负责存储键对、处理冲突等。例如,存储密码时,系统可能用MD5生成密码摘要,再将摘要存入数据库(而非哈希表)。 --- ### 三、典型应用场景对比 | **技术** | **用途** | **示例** | |----------|---------------------------|------------------------------------------| | MD5 | 数据完整性校验、密码哈希化 | 文件传输后对比MD5验证是否一致 | | 哈希表 | 高效数据存储与快速检索 | 数据库索引、缓存系统(如Redis)[^2][^3] | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值