数据结构和算法——散列函数的构造方法(直接定址法、除留余数法、数字分析法、折叠法、平方取中法、ASCII码加和法、前三字符移位法)

简介: 数据结构和算法——散列函数的构造方法(直接定址法、除留余数法、数字分析法、折叠法、平方取中法、ASCII码加和法、前三字符移位法)

数字关键词的散列函数构造

一个“好”的散列函数一般应考虑下列两个因素

  1. 计算简单,以便提高转换速度;
  2. 关键词对应的地址空间分布均匀,以尽量减少冲突。

直接定址法

取关键词的某个线性函数值为散列地址,即 (a、b为常数)。

例如以年份(1990-2011)为关键词,那么就可以将散列函数构造成 image.png

除留余数法

散列函数为:

例如上篇里提到的:

地址 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
关键词 34 18 2 20 23 7 42 27 11 30 15

这里的散列函数就为:h(key) = key % 17

  • 此处p = TableSize = 17
  • 一般地,p取素数

选择素数p可以避免余数之间的相关性,降低哈希冲突的概率。如果选择合数作为模数,可能存在公因数,增加了冲突的概率。

数字分析法

分析数字关键字在各位上的变化情况,取比较随机的位作为散列地址。

比如:取11位手机号码key的后4位作为地址,则散列函数为: (char *key)

即,手机号码为12345678910,其地址就为“8910”。

例子

关键词key是18位的身份证号码: image.png 根据分析,发现变化比较大的就是我们标红的六位,所以我们以他们六位来设计散列函数:

当key[18] = ‘X’时,

当key[18]为‘0’~‘9’时,

(以十进制来计算地址,所以最高位为10的5次方)

折叠法

把关键词分隔成位数相同的几个部分,然后叠加。

比如:56793542,拆分成三部分

,取后三位391,所以h(56793542) = 391

平方取中法

将一个数平方之后再取中间位数的值。

比如:56793542

所以h(56793542)=641

字符关键词的散列函数构造

ASCII码加和法

对字符型关键词key定义散列函数如下:




但是这种方法冲突比较严重,a3(97+3)、b2(98+2)、c1(99+1)的ASCII码值加起来都等于100,eat(101+97+116)和tea(116+101+97)的ASCII码值加起来都等于314.


进行一下简单的改进

前三字符移位



(这里用27进制计算地址,原因是包括空格在内的单个字符共有27个)


但是这种方法仍然容易冲突:string、street、strong、structure等等;


而且会造成空间浪费,理论上来说,前三字符所有可能性的组合为种,但经过统计得到,实际中的组合约3000种,,即空间利用率大约30%,浪费了70%的空间。

移位法

涉及关键词所有n个字符,并且分布得很好;

例如:h(“abcde”) = ‘a’ * + ‘b’ *  + ‘c’ *  + ‘d’ * 32 + ‘e’。

用这个计算方法需要乘10次,我们看一下比较快的计算方法:

h(“abcde”) = (((‘a’ * 32 + b) * 32 + c) * 32 + d ) * 32 + e,

用这种方法,在计算时就只需要乘4次

还有没有更巧妙的办法呢?

我们发现32是2的5次方,于是可以通过移位,也就是将一个数往左二进制移位五次,就相当于*32.

于是有:

Index Hash(const char *Key, int TableSize)
{
    unsigned int h = 0; /* 散列函数值,初始化为0  */
    while( *Key != '\0')
    {
        h = (h << 5) + *Key++;
    }
    return h % TableSize;
}

end



目录
相关文章
|
1月前
|
算法 前端开发 数据处理
小白学python-深入解析一位字符判定算法
小白学python-深入解析一位字符判定算法
47 0
|
1月前
|
机器学习/深度学习 算法 搜索推荐
从理论到实践,Python算法复杂度分析一站式教程,助你轻松驾驭大数据挑战!
【10月更文挑战第4天】在大数据时代,算法效率至关重要。本文从理论入手,介绍时间复杂度和空间复杂度两个核心概念,并通过冒泡排序和快速排序的Python实现详细分析其复杂度。冒泡排序的时间复杂度为O(n^2),空间复杂度为O(1);快速排序平均时间复杂度为O(n log n),空间复杂度为O(log n)。文章还介绍了算法选择、分而治之及空间换时间等优化策略,帮助你在大数据挑战中游刃有余。
57 4
|
1月前
|
存储 人工智能 算法
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
这篇文章详细介绍了Dijkstra和Floyd算法,这两种算法分别用于解决单源和多源最短路径问题,并且提供了Java语言的实现代码。
69 3
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
|
1月前
|
机器学习/深度学习 存储 缓存
数据结构与算法学习十:排序算法介绍、时间频度、时间复杂度、常用时间复杂度介绍
文章主要介绍了排序算法的分类、时间复杂度的概念和计算方法,以及常见的时间复杂度级别,并简单提及了空间复杂度。
24 1
数据结构与算法学习十:排序算法介绍、时间频度、时间复杂度、常用时间复杂度介绍
|
21天前
|
并行计算 算法 IDE
【灵码助力Cuda算法分析】分析共享内存的矩阵乘法优化
本文介绍了如何利用通义灵码在Visual Studio 2022中对基于CUDA的共享内存矩阵乘法优化代码进行深入分析。文章从整体程序结构入手,逐步深入到线程调度、矩阵分块、循环展开等关键细节,最后通过带入具体值的方式进一步解析复杂循环逻辑,展示了通义灵码在辅助理解和优化CUDA编程中的强大功能。
|
29天前
|
存储 算法 Java
Set接口及其主要实现类(如HashSet、TreeSet)如何通过特定数据结构和算法确保元素唯一性
Java Set因其“无重复”特性在集合框架中独树一帜。本文解析了Set接口及其主要实现类(如HashSet、TreeSet)如何通过特定数据结构和算法确保元素唯一性,并提供了最佳实践建议,包括选择合适的Set实现类和正确实现自定义对象的hashCode()与equals()方法。
32 4
|
1月前
|
搜索推荐 算法
数据结构与算法学习十四:常用排序算法总结和对比
关于常用排序算法的总结和对比,包括稳定性、内排序、外排序、时间复杂度和空间复杂度等术语的解释。
19 0
数据结构与算法学习十四:常用排序算法总结和对比
|
1月前
|
存储 缓存 分布式计算
数据结构与算法学习一:学习前的准备,数据结构的分类,数据结构与算法的关系,实际编程中遇到的问题,几个经典算法问题
这篇文章是关于数据结构与算法的学习指南,涵盖了数据结构的分类、数据结构与算法的关系、实际编程中遇到的问题以及几个经典的算法面试题。
29 0
数据结构与算法学习一:学习前的准备,数据结构的分类,数据结构与算法的关系,实际编程中遇到的问题,几个经典算法问题
|
1月前
|
机器学习/深度学习 存储 算法
【初阶数据结构】算法效率大揭秘 | 时间与空间复杂度的深度剖析
【初阶数据结构】算法效率大揭秘 | 时间与空间复杂度的深度剖析
|
2月前
|
机器学习/深度学习 算法 Java
[算法与数据结构] 谈谈线性查找法~
该文章详细介绍了线性查找法的基本概念与实现方法,通过Java代码示例解释了如何在一个数组中查找特定元素,并分析了该算法的时间复杂度。