Hash初步

本文介绍了Hash的基本原理及其在计算机科学中的应用。通过使用散列函数将输入数据转换为固定长度的输出,即散列值,从而实现高效的数据查找。文章还讨论了如何选择合适的Hash函数以减少冲突,并给出了几种解决冲突的方法。
本文初步介绍Hash的原理及用途,萌新的博客不比那些神犇,网上的大佬的博客实在是让萌新佩服得五体投地,但是萌新还是想发表一篇博客来陶冶一下自己的情操(说得很高大上)。

现在Hash已经广为程序员所知,但是Hash的由来确鲜为人知,所以作为蒟蒻的我肯定也不知道,毕竟连百度百科也没有解答这一疑问。而且作为一个蒟蒻旨在写出简单易懂、益于初学者理解的博客,我自然不可能把百度百科上的玄学东西放上来。Hash,一般翻译做“散列”,通过散列算法,变换成固定长度的输出,该输出就是散列值。(一言不合就放百度百科)。

这里写图片描述

    好吧,我错了。

举个例子,我们要查找数组里的值是否出现过,一般的方法是把数组遍历一遍就可以找到是否出现过,这样的时间复杂度为O( n),在很多题目中你敢这样干就意味着数据干把你卡爆。
最快的方法是直接利用元素的值作为数组的下标,可以直接查找,这样的时间复杂度为O( 1 ),但是大部分时间你敢这样干,内存绝对会爆掉。
岂不是很尴尬????

这个Hash就会发挥出它的作用。当我们要储存的元素为10^9时,即使开bool数组内存也会爆掉,这个时候就学要用一个函数建立一个映射关系(数学知识在这里就不详讲了)。把10^9变成一个小一点的数,我们就可以用数组来进行储存(是不是很棒棒)。如果你曾经看过我的离散优化初步的博客,你可能就会恍然大悟。离散优化也是一种Hash。我们是把线段的长度映射为端点进行储存达到节约空间的目的,同时也用O(1)的时间就完成了查找。
看到这里,你可能大概明白了Hash是什么。Hash就是个映射。

这里写图片描述

用某种神奇的函数建立某种神奇的映射关系。——摘自大佬Apache553

同样不同的Hash,也有不同的等级之分,这主要是取决于Hash函数的优劣。一个Hash函数的优劣由这个Hash函数冲突的多少有关。冲突越多Hash就越垃圾,冲突越少Hash就越好。所以Hash的关键在于Hash函数的选择。网上大佬的博客里对如何建立一个优秀的Hash映射关系的建立已经介绍得很详细了。这里就不在赘述。

对Hash冲突的会在接下来博客中为大家介绍,如果大家急切地想知道,就去看点击重新加载的博客,里面详细介绍了Hash拉链法(有冲突发生就把这个元素链在后面,大致与邻接表相同,如图)解决冲突(据他说是很详细)。

根据原作 https://pan.quark.cn/s/459657bcfd45 的源码改编 Classic-ML-Methods-Algo 引言 建立这个项目,是为了梳理和总结传统机器学习(Machine Learning)法(methods)或者算法(algo),和各位同仁相互学习交流. 现在的深度学习本质上来自于传统的神经网络模型,很大程度上是传统机器学习的延续,同时也在不少时候需要结合传统法来实现. 任何机器学习法基本的流程结构都是通用的;使用的评价法也基本通用;使用的一些数学知识也是通用的. 本文在梳理传统机器学习法算法的同时也会顺便补充这些流程,数学上的知识以供参考. 机器学习 机器学习是人工智能(Artificial Intelligence)的一个分支,也是实现人工智能最重要的手段.区别于传统的基于规则(rule-based)的算法,机器学习可以从数据中获取知识,从而实现规定的任务[Ian Goodfellow and Yoshua Bengio and Aaron Courville的Deep Learning].这些知识可以分为四种: 总结(summarization) 预测(prediction) 估计(estimation) 假想验证(hypothesis testing) 机器学习主要关心的是预测[Varian在Big Data : New Tricks for Econometrics],预测的可以是连续性的输出变量,分类,聚类或者物品之间的有趣关联. 机器学习分类 根据数据配置(setting,是否有标签,可以是连续的也可以是离散的)和任务目标,我们可以将机器学习法分为四种: 无监督(unsupervised) 训练数据没有给定...
03-15
### 哈希表的定义与基本原理 哈希表是一种基于键映射的数据结构,其核心在于通过哈希函数将键转换为存储位置索引,从而实现高效的数据存取操作[^1]。这种特性使得哈希表在查找、插入和删除操作上通常能够达到接近常数时间复杂度 \(O(1)\) 的性能。 #### 哈希函数的作用 哈希函数是哈希表的核心组件之一,负责将输入的关键字转化为对应的存储地址。理想情况下,一个好的哈希函数应具备以下几个特点: - **均匀分布**:尽可能减少不同关键字之间的碰撞概率。 - **计算效率高**:能够在较短时间内完成运算。 - **确定性**:对于相同的输入始终返回一致的结果。 然而,在实际应用中完全避免冲突几乎是不可能的任务,因此如何有效处理这些不可避免的情况成为设计良好哈希表的重要环节。 ### 处理哈希冲突的法 当两个不同的关键字经过同一哈希函数得到相同散列时即发生了所谓的“哈希冲突”。针对这种情况有多种解决案: #### 链地址法(Separate Chaining) 这是最常用的一种法,也是 Redis 中所采用的技术路线[^2]。具体做法是在每一个桶位维护一个链表或者更复杂的动态集合用来容纳所有映射至此处的对象实例们;如此一来即便存在多个元素共享同一个槽位也无妨因为它们会被串联起来形成一条逻辑上的链条供后续检索使用。 #### 开放寻址法(Open Addressing) 不同于前者单独开辟额外空间存放溢出项的式,“开放定址”则试图在同一张表格内部寻找其他可用空闲单元格作为替代案。常见的变种包括线性探测、二次探查以及双哈希策略等[^3]。 ##### 双哈希法示例分析 假设我们要向容量大小固定的数组型容器里依次加入若干整数并遵循特定规则调整定位偏差直至找到合适的目标站点为止。例如给定初始条件如下所示: - 数组长度设为 17; - 待插入序列包含 {18, 35} 这两成员; 按照常规流程先分别求得各自对应的第一候选坐标分别为 `1` 和同样也为 `1` ,显然此时出现了重复占用现象需进一步采取措施加以区分修正——引入辅助增量机制重新计算目标偏移量即可达成目的。这里选取参数 R=7 来参与构建第二级判定依据公式表达式如下: \[ \text{new\_index} = (\text{original\_index} + i * (R - (\text{key}\%R))) \% N\] 其中变量含义解释如下: - original_index 表征原始试探所得初步结论; - key 则代表当前正在考虑的具体待安置对象身份标识符; - 参数i表示尝试次数逐步累加递增趋势体现探索过程中的不断改进意图; 最后再利用整个数组总规模N做最终约束确保不会越界超出边界范围之外。 ### Python 实现简单版哈希表 下面给出一段简单的 python 程序片段用于演示上述理论知识的实际编码表现形式: ```python class HashTable: def __init__(self, size): self.size = size self.table = [[] for _ in range(size)] def hash_function(self, key): return key % self.size def insert(self, key): index = self.hash_function(key) bucket = self.table[index] found = False for idx, record in enumerate(bucket): if record == key: bucket[idx] = key found = True break if not found: bucket.append(key) def search(self, key): index = self.hash_function(key) bucket = self.table[index] for k in bucket: if k == key: return True return False ht = HashTable(10) keys_to_insert = [10, 20, 30, 40, 50] for key in keys_to_insert: ht.insert(key) print(ht.search(20)) # Output should be True ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值