IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 哈希表又名离散表查找 -> 正文阅读

[数据结构与算法]哈希表又名离散表查找

散列技术是在记录的储存位置和它的关键字建立一种确定的对应关系f,使得每个关键字key对应一个储存位置(key)。查找时,根据这个确定的对应关系找到给定值key对应的映射f(key),若查找集合中存在的记录,则必在f(key) 的位置上。

这里我们把这种对应关系f称为散列函数,又称为哈希函数。按照这个意思,采用散列技术将记录存储在一块连续的存储空间中,这块连续的存储空间称为散列表或者哈希表

哈希表查找步骤:

1.在存储时,通过散列函数计算记录的散列地址,并按此地址存储该记录。

2.当查找记录时,我们通过同样的散列函数计算记录的散列地址,按此散列地址访问该记录。很简单,在哪里存,就在哪里找。

所以说,散列技术既是一种存储方法,也是一种查找方法。它与线性表,图等结构不同的是,前面几种元素之间存在某种逻辑关系,可以用线性图示表示出来,而散列技术的记录之间不存在什么逻辑关系,它只与关键字有关。因此,散列技术主要是面向查找的存储结构。

散列技术最合适的求解问题是查找与给定值相等的记录。它简化了过程比较,效率就会大大提高。但是,散列技术不具备很多常规数据结构的能力。

  • 同样的关键字有很多的记录存在。如:公司找人你要按照男女去找那就难受了啊,一个女可能对应很多人的,但是按照公司的工作号去找那就倍儿快。
  • 不适合范围查找,你不能找一个公司中30-40岁之间的员工,也不能找年龄最大或者最小的员工,甚至你无法对哈希表排序。

散列函数的构造方法:

两个原则:

  1. 计算简单。
  2. 散列地址分布均匀,这样可以保证空间的利用率,并减少处理冲突的时间。

构造方法:

  1. 直接地址法:去关键字的某个线性函数值为散列地址,f (key) = a * key +? b.这样的散列函数优点就是简单均匀,也不会产生冲突,但问题是这需要事先知道关键字的分布情况,适合查找表较小且连续的情况。由于这样的限制,此方法虽然简单,但现实中并不常用。
  2. 数字分析法:比如手机号,182****8213你就知道,这是移动的手机号,并且能锁定那个人。截取有效关键字,这是散列技术常用到的手段。数字分析法通常适合处理关键字比较大的情况,如果事先知道关键字的分布,就可以考虑这个方法。
  3. 平方取中法:比如数字1234,平方1522756,在抽取中间三位227,用作散列地址。它适用于不知道关键字的分布,而位数又不是很大的情况。
  4. 折叠法:将关键字从左到右分割成相等的几部分(最后一位不够就让它短吧),然后把这几部分叠加求和,并按照散列表长,取最后几位作为列数地址。如:关键字9876543210,散列表长为3位,我们将它分成四组:987 654 321 0 然后叠加求和 987 + 654 + 321 + 0 = 1962,再取后三位得散列地址,962。有时这样还不能保证分布均匀,不妨从一端向另一端折叠后对齐相加。如把987 和 654 反转,再与 654 和 0 相加 ,1566,所以散列地址为556。折叠法实现不知道关键字的分布,适合关键字位数较多的情况。

处理散列冲突的方法:

  1. 开放定址法:发生冲突,就去寻找下一个空的散列地址只要散列表足够大,空的散列地址总能够找到,并将记录存入。解决冲突的开放定址法有:线性探测法,二次探测法。本来不是同一个词儿取要争夺同一个空间的现象叫堆积。
  2. 在散列函数法:f_{i}(key) = RH_(i) (i = 1,2,3,...,k)。我们可以把我们前面说的折叠法,平方取中法都用上,放生冲突我们就换一个函数。
  3. 链地址法:将所有的关键字为同义词的记录存储在一个单链表中。这样已经不存在什么冲突地址,无论多少冲突,我们增加结点就可以解决。

Java代码实现:

	// 哈希表
	public DataArray(int[] paraKeyArray, String[] paraContentArray, int paraLength) {
		// 初始化
		length = paraLength;
		data = new DataNode[length];

		for (int i = 0; i < length; i++) {
			data[i] = null;
		} // Of for i

		// 第二步
		int tempPosition;
		for (int i = 0; i < paraContentArray.length; i++) {
			// 构建哈希表
			tempPosition = paraKeyArray[i] % paraLength;

			// 寻找一个空位
			while (data[tempPosition] != null) {
				tempPosition = (tempPosition + 1) % paraLength;
				System.out.println("Collision,move forward for key " + paraKeyArray[i]);
			} // Of while

			data[tempPosition] = new DataNode(paraKeyArray[i], paraContentArray[i]);
		} // Of for i
	} // Of the constructor

	// 哈希查找
	public String hashSearch(int paraKey) {
		int tempPosition = paraKey % length;
		while (data[tempPosition]!=null) {
			if (data[tempPosition].key == paraKey) { // 判断关键字是否相等。
				return data[tempPosition].content; // 返回内容
			} // Of if
			System.out.println("Not this one for "+paraKey);
			tempPosition = (tempPosition+1)%length;
		} // Of while
		return "null";
	} // Of hashSearch

完整代码

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-01-30 19:10:58  更:2022-01-30 19:12:35 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 18:35:05-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码