散列函数的设计

  • 散列查找的基本思想
  • 散列函数的设计原则
  • 三种常见的散列函数
    • 1. 直接定址法
    • 2. 除留余数法
    • 3. 平方取中法
  • 处理冲突的方法
    • 1. 开放定址法
    • 2. 拉链法(链地址法)

散列查找的基本思想

在记录的存储位置和它的关键码之间建立一个确定的对应关系H,使得每个关键码key和唯一的存储位置H(key)相对应。

存储记录时,根据这个对应关系找到关键码的映射地址,并按此地址存储该记录;查找记录时,根据这个对应关系找到待查找关键码的映射地址,并按此地址访问该记录。

采用散列技术将记录存储在一块连续的存储空间中,这块连续的存储空间称为散列表(hash table),将关键码映射为散列表中适当存储位置的函数称为散列函数(hash function),所得到的存储位置成为散列地址(hash address)。

散列函数的设计原则

  1. 计算简单。散列函数不应该有很大的计算量,否则会降低查找效率。
  2. 函数值(即散列地址)分布均匀,希望散列函数能够把记录以相同的概率“散列”到散列表的所有地址空间中,这样才能保证存储空间的有效利用,并减少冲突。

三种常见的散列函数

1. 直接定址法

直接定址法的散列函数是关键码的线性函数,即:
H(key) = a × key + b(a,b为常数)
例如,关键码集合为{10,30,50,70,80,90},选取H(key) = key/10。则散列表如下图所示。

直接定址法的特点是不会产生冲突,但实际应用中能使用这种散列函数的情况很少。它适用于事先知道关键码的分布,关键码集合不是很大且连续性较好的情况。

2. 除留余数法

除留余数法的基本思想是:选择某个适当的正整数p,以关键码除以p的余数作为散列地址,即:
H(key) = key mod p
可见这个方法的关键在于选取合适的p,否则容易产生同义词。例如,若p含有质因子,例如p = m × n,则所有含有m或n因子的关键码的散列地址均为m或n的倍数,如下图所示

显然,这增加了冲突的机会。一般情况下,若散列表表长为m,通常选p小于或等于表长(最好接近m)的最小素数或不包含小于20质因子的合数。

3. 平方取中法

平方取中法是对关键码平方后,按散列表大小,取中间若干位作为散列地址(简称平方后截取),其原理是一个数平方后,中间的几位分布较均匀,从而冲突发生的概率较小。
例如,对于关键码1234,假设散列地址是2位,由于1234×1234=1522756,选取中间的两位作为散列地址,可以选22也可以选27.
平方取中法通常用在事先不知道关键码的分布且关键码的位数不是很大的情况。

处理冲突的方法

通常情况下,由于关键码的复杂性和随机性,很难找到理想的散列函数。如果某记录按散列函数计算出的散列地址加入散列表时产生了冲突,就必须再找一个地方来存放它,因此,需要有合适的处理冲突方法。下面列出两种常用的处理冲突的方法。

1. 开放定址法

开放定址法处理冲突的方法是,如果由关键码得到的散列地址产生了冲突,根据(H(key) + d)% m 寻找下一个空的散列地址。
例:设关键码集合{47,7,29,11,16,92,22,8,3},散列表表长为11,散列函数为H(key) = key mod 11,用开放定址法处理冲突,得到的散列表如图所示,具体过程如下:
H(47)=3,H(7)=7,没有冲突,直接存入;
H(29)=7,发生冲突,(H(29)+1)%11=8,散列地址8为空,将29存入;
H(11)=0,H(16)=5,H(92)=4,没有冲突,直接存入;
H(22)=0,发生冲突,(H(22)+1)%11=1,散列地址1为空,将22存入;
H(8)=8,发生冲突,(H(8)+1)%11=9,散列地址9为空,将8存入;
H(3)=3,发生冲突,(H(3)+1)%11=4,仍然冲突,(H(3)+2)%11=5,仍然冲突,(H(3)+3)%11=6,散列地址6为空,将3存入


算法定义:

int HashTableSearch(int *ht, int k){int i, j = H(k);    //计算散列地址i = j;             //设置比较的起始位置while(ht[i] != 0){if(ht[i] == k) return i;    //查找成功else i = (i + 1) % MaxSize; //向后探测一个位置}return -1;   //查找失败
}

2. 拉链法(链地址法)

基本思想: 将所有散列地址相同的记录,及所有关键码为同义词的记录存储在一个单链表中——称为同义词子表(synonym table),在散列表中存储的是所有同义词子表的头指针。
开散列表的类定义和查找方法

template <typename DataType>
class Node{public:Node<DataType> *next;DataType data;
};const int MaxSize = 100;
class HashTable{public:HashTable();    //构造函数,初始化开散列表~HashTable();   //析构函数,释放同义词子表结点int Insert(int k);int Delete(int k);Node<int> *Search(int k);
private:int H(int k);Node<int> *ht[MaxSize];
};HashTable::HashTable(){for (int i = 0; i < MaxSize; ++i)ht[i] = nullptr;
}HashTable::~HashTable(){Node<int> *p = nullptr, *q = nullptr;for (int i = 0; i < MaxSize; ++i){p = q = ht[i];while(p != nullptr){p = p->next;delete q;q = p;}}
}Node<int>* HashTable::Search(int k){int j = H(k);   //计算散列地址Node<int> *p = ht[j];   //工作指针p初始化while(p != nullptr){if(p->data == k) return p;else p = p->next;}return nullptr; //查找失败
}

【数据结构--散列函数】相关推荐

  1. 一些基础的算法知识——《图解算法》

    1.可使用图算法编写跟踪用户的AI系统:使用K最近邻算法编写推荐系统: 2.二分查找 1)一般而言,对于包含n个元素的列表,用二分查找最多需要步,而简单查找最多需要n步(一般的log指的是): 2)仅 ...

  2. 数据结构与算法——17. 散列(哈希)与完美散列函数

    文章目录 一.散列(Hashing)的概念 举例说明 二.完美散列函数 1. 数据的一致性校验 2. 完美散列函数用于数据的一致性校验 一.散列(Hashing)的概念 在查找算法中,如果数据项之间是 ...

  3. 数据结构Java10【哈希表概述、散列函数的设计、散列冲突解决方案】

    学习地址:[数据结构与算法基础-java版]                  

  4. C++(数据结构与算法):30---散列(哈希)表的介绍(散列函数、散列冲突、散列溢出)

    一.散列(哈希)介绍 散列使用一个散列函数(也称为哈希函数)把字典的数对映射到一个散列表(也称为哈希表)的具体位置 散列的存储与查找: 查找:如果数对p的关键字是k,散列函数为f,那么在理想的情况下, ...

  5. 数据结构与算法——19. 散列函数设计方法

    文章目录 一.散列(哈希)函数设计方法 1. 折叠法 2. 平方取中法 二.散列函数设计:非数项 总结 一.散列(哈希)函数设计方法 1. 折叠法 折叠法设计散列函数的基本步骤: 将数据项按照位数分为 ...

  6. 数据结构—— 构造散列函数的六种方法【直接定址法-数字分析法-平方取中法-折叠法-除留余数法-随机数法】

    目录: 一:直接定址法 二:数字分析法 三:平方取中法 四:折叠法 五:除留余数法 六:随机数法 这些方法原理都是将原来数字按某种规律变成另一个数字 一:直接定址法 取关键字的某个线性函数值作为散列地 ...

  7. 考研数据结构之查找(9.8)——练习题之使用散列函数H(k)= 3k mod 11并采用链地址法处理冲突并构造散列表及设计散列表的完整算法(C表示)

    题目 使用散列函数: H(k)= 3*k mod 11 并采用链地址法处理冲突.试对关键字序列(22, 41, 53, 46, 30, 13, 01, 67)构造散列表,求等概率情况下查找成功的平均查 ...

  8. 数据结构题及c语言版答案9.14,十套数据结构试题+答案+难题解析(精校版)

    十套数据结构试题+答案+难题解析(精校版) 更新时间:2017/2/9 10:47:00  浏览量:643  手机版 数据结构试卷(一) 一.单选题(每题 2 分,共20分) 1. 栈和队列的共同特点 ...

  9. 数据结构与算法常用名词术语整理

    binary search 二分查找 half-interval search  折半查找 logarithmic search  对数搜索 sentinel 哨兵 pivot 基准数 median ...

最新文章

  1. NewPhy.-揭秘优势种dominant species
  2. python中的open函数实例_Python中open函数注意点
  3. SparkStreaming使用checkpoint存在的问题及解决方案
  4. NET中的异步编程(二)- 传统的异步编程
  5. java和C操作数组的一个小区别
  6. Node Capital生态布局初成,部分项目差强人意
  7. 【机器学习】L1正则化与L2正则化详解及解决过拟合的方法
  8. python dict底层实现_dict实现原理和哈希表
  9. CVE-2015-1635-HTTP.SYS远程执行代码漏洞(ms15-034)
  10. 锐浪HTML5报表实际应用方法,解决锐浪Grid++报表在谷歌等浏览器不兼容的尴尬局面
  11. mysql索引,索引结构,索引类型,索引失效
  12. python发邮件被认定为垃圾邮件_Python:脚本发送的邮件被Gmail标记为垃圾邮件
  13. Navicat 连接数据库报错:1045-Access denied for user ‘root‘@‘localhos
  14. windows10下安装Box2D
  15. 使用 React 和 Vite 使用 Tauri 构建番茄钟
  16. java获取中文的拼音以及获取中文拼音的首字母
  17. Linux:安装ruby
  18. Android手机如何修改DPI触发平板模式
  19. PHP代码审计8—SSRF 漏洞
  20. CMake 常用总结二:CMake 生成静态库与动态库

热门文章

  1. sorted 实现部分排序
  2. Win系统如何取消f1打开浏览器
  3. 最强大易用的开源MODBUS库-YMODBUS,包含MASTER/SLAVE
  4. EMV规范(三)——应用初始化
  5. 个人博客 HTML个人介绍网页 学生个人网页设计作品 学生个人网页模板 简单个人主页成品 个人网页制作 HTML学生个人网站作业设计
  6. 究竟新买的手机电池第一次要充多久的电
  7. 直接内存 直接内存的释放和回收
  8. 2021-06-21 12点 程序外生活 - 中国A50指数 机器预测学习跟踪记录 - 周六反弹失败,等待跌完,继续等待4小时第一个底分型出现。周月线持续跌势。
  9. WORD: 如何在一个word里文档里创建多个目录?
  10. Auto.js修改QQ语音+破解闪照