哈希算法:冲突解决与高效查找

一、哈希概念

又称散列,是一种组织数据的方式。本质就是通过哈希函数把关键字key跟存储位置建立一个映射关系,查找时通过这个哈希函数,计算出key存储的位置,进行快速查找。

1.1直接定位法

当关键字的范围比较集中时,简单高效,但局限性太大(而且必须是整形)

1.2哈希冲突

假设我们只有数据范围是[0,9999)的N个值,我们要映射到一个M个空间的数组中(一般情况下M。=N),那么就要借助哈希函数,关键字key被放到数组的h位置,注意h计算的值必须在[0,M)之间。

那么这里就会存在一个问题,两个不同的key可能会映射到用一个位置,这是无法避免的,所以就要尽可能的设计优秀的哈希函数

1.3负载因子

假设哈希表中已经映射存储了N给值,哈希表大小是M,负载因子为N/M。负载因子越大,哈希冲突的概率越高,空间利用率越高;负载因子越小,哈希冲突的概率越小,空间利用率越低。

越小越好。

1.4将关键字转为整形

我们把关键字映射到数组中位置时,一般时整形好做映射计算。

1.5哈希函数

一个好的哈希函数应该让N个关键字被等概率的均匀的散列分布到哈希表的M个空间中,但实际却和很难做到,所以需要认真设计

1.51除法散列法/除留余数法

假设N==100,[0,9999],哈希表的大小为M,那么通过key除以M的余数作为映射位置的下标

h(key)=key/M

 避免M是2或10的幂,key会重复很多,建议M取不太接近2的整数次幂的一个质数

eg.key =123456

int hashi = key%2^16

int hashi = key&(1<<16-1)  key只取后16位

int n =16;

int hashi = key&(1<<n-1)

用key’=key>>16,将key和key‘异或结果作为哈希值,尽量让key所有的位都参与计算

 

1.6处理哈希冲突

1.61开放定址法(比较搓)

在开放地址法中所有的元素都放到哈希表里,当一个关键字key用哈希函数计算出的位置冲突了,则按照某种规则找到一个没有存储数据的位置进行存储。

有三种规则:线性探测,二次探测,双重探测

eg{19,30,5,36,13,20,21,12}映射到M=11的表中

a、线性探测,但会出现堆积

看似只有19和30的hash0位置冲突,但其实20和21也在抢位置

hc = (key.i)=hashi = (hashi0+i)/M   i={1,2,3,...,M-1}  最多探测M-1次

注意给每一个存储值的位置加一个状态标识,否则删除一些值以后,会影响后面冲突的值的查找

{EXIST,EMPTY,DELETE}

从发生冲突的位置开始,依次线性向后探测,直到寻找到下一个没有存储数据的位置为止,如果走到哈希表尾,则回绕到哈希表头的位置

b、二次探测

依次左右按二次方跳跃探测

h(key)= hash0=key%M

hc(key,i) = hashi=(hash0+-i^2)%M,i={1,2,3,...M/2}

当hashi=(hash0-i^2)%M时,当hashi<0时,需要hashi+=M

eg.将{19,30,52,63,11,22}映射到M=11表中

h(19)=8  h(30)=8  h(52)=8  h(63)=8  h(11)=0  h(22)=0

c、双重散列(了解即可,不实用)

第一个哈希函数计算出的值发生冲突,使用第二个哈希函数,计算出一个跟key相关的偏移值,不断往后探测

h1(key)=hasg09=key%M

hc(key,i)=hashi=(hash0+i*h2(key))%M  i={1,2,3,...,M}

1.5.2乘法散列法(对哈希表大小M没有要求)

用关键字乘上常数A(0<A<1),并抽取出k*A的小数部分,后再用M乘以k*A的小数部分,再向下取整。

1.5.3全域散列法

如果存在一个恶意的对手,他针对我们提供的散列函数,特意构造出一个发生严重冲突的数据集,比如让所有关键字全部落入同一位置中

方法:见招拆招,给散列函数增加随机性,攻击者无法找到确定可以导致最坏情况的数据,即全域散列

ha(key)=((a*key+b)%p)%M

p需要选一个足够大的质数,a选[1,p-1],b选[0,p-1]

需要注意每次初始化哈希表时,随机选取全域散列函数组中的一个散列函数使用,后读增删查改都固定使用这个散列函数,否则每次哈希都是随机选一个散列函数,那么插入是一个散列函数,查找又是另一个函数,就会导致找不到插入的key了

1.6.3 链地址法

开放地址法负载因子必须小于1,链地址法的负载因子就没有限制了,可以大于1,但为了哈希冲突概率低,空间利用率,大部分还是控制在1,大于1就扩容

 

二、代码实现

A、标准

1、插入

但是上面这种扩容有些太复杂了,可改用如下代码

能交换必须优先考虑,赋值麻烦还会涉及深拷贝

 

2、查找

3、删除

B、链式

1、插入

2、查找

3、删除

Read more

双重机器学习之因果推断 | CATE条件平均处理效应估计:五大方法原理详解与模拟数据实战(python版)

家人们我又更新了,代码和科研绘图在论文末尾,欢迎大家评论点赞和收藏,你们的认可是我坚持的动力,祝大家科研顺利。 因果推断 | CATE条件平均处理效应估计:五大方法原理详解与模拟数据实战 本文是因果推断系列文章。本篇聚焦 CATE(Conditional Average Treatment Effect,条件平均处理效应) 的估计,从ATE的局限性讲起,深入介绍S-Learner、T-Learner、X-Learner、因果森林DML和线性DML五种主流方法的原理,并在模拟数据上进行完整的代码实操与效果对比。 1 从ATE到CATE:为什么需要异质性处理效应? 1.1 ATE只能回答"平均有没有用" ATE(Average Treatment Effect)回答的是:干预措施对整个群体的平均效果是什么? 但在实际业务中,我们更想知道的是:对于不同的个体或子群,干预效果有什么不同? 举几个例子: * 精准营销:给所有人发满减券ATE为正,但拆开看,高消费用户根本不需要券,低消费用户反而是增量用户——CATE帮你找到真正的增量人群。 * 个性化医疗:

By Ne0inhk

Python 办公自动化:批量处理 Excel/Word/PPT 实战教程

第一部分:准备工作——搭建你的自动化武器库 Python环境安装与配置 在开始自动化之旅前,首先需要搭建好Python运行环境。前往Python官网下载对应操作系统的安装包,建议选择3.7及以上版本。安装时务必勾选“Add Python to PATH”选项,这样可以在命令行中直接使用Python命令。 安装完成后,打开命令提示符(Windows)或终端(Mac/Linux),输入 python --version 验证安装是否成功。如果显示Python版本号,说明环境已就绪。 核心第三方库概览 Python之所以强大,很大程度上得益于其丰富的第三方库。针对办公自动化,我们需要安装以下几个核心库: 处理对象核心库主要功能Excelopenpyxl、pandas读写Excel文件、数据处理与分析Wordpython-docx读取、修改、创建Word文档PPTpython-pptx创建和修改PowerPoint演示文稿PDFPyPDF2、pdfplumberPDF文件合并、拆分、文本提取 安装命令非常简单,在命令行中执行: bash pip install ope

By Ne0inhk
Python 列表内存存储本质:存储差异原因与优化建议

Python 列表内存存储本质:存储差异原因与优化建议

文章目录 * 1. 问题引入:列表存储的内存 "膨胀" * 2. 理论存储与实际存储的差异 * 2.1 64位整数的存储差异 * 2.2 短字符串的存储差异 * 3. 列表的内存存储本质 * 3.1 相同元素列表内存少的核心原因:对象复用 * 3.1.1 小整数的缓存复用机制 * 3.1.2 字符串的驻留(Intern)机制 * 3.2 不同元素列表内存高的原因:对象重复创建 * 3.2.1 不同整数的内存开销 * 3.2.2 不同字符串的内存开销 * 4. 内存占用对比分析 * 5. 优化建议:利用对象复用减少内存开销 * 6. 总结

By Ne0inhk
【Python基础】(五)Python 库使用全攻略:从标准库到第三方库,让开发效率翻倍

【Python基础】(五)Python 库使用全攻略:从标准库到第三方库,让开发效率翻倍

目录 编辑 前言 一、Python 库的核心认知:什么是库?为什么要用库? 1.1 库的本质:现成的 "代码工具箱" 1.2 库的分类:标准库 vs 第三方库 (1)标准库:Python 自带的 "基础工具箱" (2)第三方库:全球开发者共建的 "扩展工具箱" 1.3 使用库的核心优势:效率翻倍的关键 二、标准库实战:内置工具的高效用法 2.1 日期时间处理:datetime库(计算日期差、格式转换) 实战需求:计算你和心爱的人认识多少天 扩展用法:

By Ne0inhk