Hash哈希学习笔记

概念:通过一个hash函数建立值与存储地址的关系

原则:

  • 开小数组+冲突解决
  • 冲突越少,用时越少;可通过调整余数或优质的hash算法尽量使hash值分散,减少碰撞

hash算法的构成:

hash函数的初始化

构造hash函数:

典型的函数包括除余法 H ( k ) = ( k ) m o d p H(k)=(k)modp H(k)=(k)modp、elfhash等等

冲突解决方法:

(常用技术)线性探测再散列技术:当 ( k ) m o d p (k)modp (k)modp下标对应有元素时,依次探测 ( k + i ) m o d p (k+i)modp (k+i)modp下标位置直至数组为空,再将元素放入。

再开数组辅助定位:

在存储后,使用hash函数定位某个元素时,不仅需要一个数组确定某个下标位置是否存在元素,当某个位置有元素时还需要一个数组存储该位置的原本元素方便精确校验是否为该元素。

拓展hash:

  • 字符串哈希
    使用elfhash算法bkdrHash算法尽可能的减少存储时的,其冲突,其他操作与经典hash无区别
    bkdrhash
    h a s h ( s ) = ( ∑ i = 1 l s [ i ] × b a s e l − i ) m o d M hash(s)=(\sum^l_{i=1} s[i]\times base^{l-i})modM hash(s)=(i=1ls[i]×baseli)modM或者
    h a s h ( s ) = ( ∑ i = 1 l s [ i ] × b a s e i − 1 ) m o d M hash(s)=(\sum^l_{i=1} s[i]\times base^{i-1})modM hash(s)=(i=1ls[i]×basei1)modM
  1. 自然溢出法
    利用C++中的unsigned long long 数据类型声明哈希值,就相当于使用大数的自然溢出为哈希值模 2 64 − 1 2^{64}-1 2641这个数。
#include<bits/stdc++.h>
#define maxn 100000
#define INF 0x3f3f3f3f
#define ull unsigned long long
using namespace std;
int N,base=233,cnt=1;
char s[2000];
ull h[maxn];
ull hashhit(char *str)
{
    ull res=0;
    int len=strlen(str);
    for(int i=0;i<len;i++)
    res=(res*base+(ull)str[i]);//自然溢出
    return res&0x7fffffff;//相当于将位数控制在int最大位数内
}
int main()
{
    scanf("%d",&N);
    for(int i=0;i<N;i++)
    {
        scanf("%s",s);
        h[i]=hashhit(s);
    }
    sort(h,h+N);
    for(int i=0;i<N-1;i++)
    if(h[i]!=h[i+1])
    cnt++;
    printf("%d",cnt);
    system("pause");
}
  1. 单哈希
    即使用一个mod值和base值计算哈希值
  2. 双哈希
    即使用两个mod值和base值确定两个哈希值,从而确定一个字符串。代码:
#include<bits/stdc++.h>//自然溢出双哈希,bkrd算法
#define maxn 100000
#define INF 0x3f3f3f3f
#define ull unsigned long long
using namespace std;
int N,base1=233,cnt=1,base2=2333;
char s[2000];
struct dhash{
    ull x;
    ull y;
}h[maxn];
ull hashhit1(char *str)
{
    ull res=0;
    int len=strlen(str);
    for(int i=0;i<len;i++)
    res=(res*base1+(ull)str[i]);//自然溢出
    return res&0x7fffffff;//相当于将位数控制在int最大位数内
}
ull hashhit2(char *str)
{
    ull res=0;
    int len=strlen(str);
    for(int i=0;i<len;i++)
    res=(res*base2+(ull)str[i]);//自然溢出
    return res&0x7fffffff;//相当于将位数控制在int最大位数内
}
int cmp(dhash a,dhash b)
{
    if(a.x!=b.x)
    return a.x<b.x;
    else
    return a.y<b.y;
}
int main()
{
    scanf("%d",&N);
    for(int i=0;i<N;i++)
    {
        scanf("%s",s);
        h[i].x=hashhit1(s);
        h[i].y=hashhit2(s);
    }
    sort(h,h+N,cmp);
    for(int i=0;i<N-1;i++)
    if(h[i].x!=h[i+1].x||h[i].y!=h[i+1].y)
    cnt++;
    printf("%d",cnt);
    system("pause");
}
  • 全排列哈希(康托展开)
    介绍:
    康托展开是一种能建立全排列与自然数之间的双射关系的方法;具体算法如下:
    自然数为X, X = a n ( n − 1 ) ! + a n − 1 ( n − 2 ) ! + . . . . + a 1 0 ! X=a_n(n-1)!+a_{n-1}(n-2)!+....+a_10! X=an(n1)!+an1(n2)!+....+a10!其中系数 a i a_i ai为全排列中所有种类的数字剔除已经出现的数字的集合,集合内小于第i位数的数字的个数。如54123,从左到右依次计算系数a,此时集合内有{1,2,3,4,5}这些数字,小于5的数字有4个,则 a 5 = 4 a_5=4 a5=4,同时剔除已经出现的数字5,集合内还剩{1,2,3,4},下一个数字为4,以此类推 a 4 = 3 , a 3 = 0 , a 2 = 0 , a 1 = 0 a_4=3,a_3=0,a_2=0,a_1=0 a4=3,a3=0,a2=0,a1=0,综上该数对应114因此,将全排列通过康托展开映射到hash表是hash算法中效率最高的选择。
  • 15
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
哈希图像检索是一种用于在大规模图像数据库中快速搜索相似图像的方法。在哈希图像检索中,图像被转换为哈希码,然后通过比较哈希码的相似性来确定图像之间的相似度。有几种常用的哈希算法可以用于图像检索,如SIFT、SURF、ORB等特征提取算法\[1\]。此外,还有一些基于哈希的图像检索方法,如VLAD、BOF等,可以用于处理海量数据的图像检索\[1\]。 在哈希图像检索中,可以使用不同的方法来计算图像之间的相似度。一种常用的方法是通过比较图像的颜色、纹理和局部特征来计算相似度\[2\]。另外,还可以使用KD-Tree、局部敏感哈希(LSH)和原子哈希函数等方法来在高维空间中进行图像检索\[2\]。 此外,还有一种基于监督学习和核的Hash算法,称为KSH算法。KSH算法利用核主要是为了解决线性不可分问题,通过监督学习学习到更有区分度的哈希值,从而降低特征维数\[3\]。 总之,哈希图像检索是一种用于在大规模图像数据库中快速搜索相似图像的方法,它可以通过提取图像特征和计算相似度来实现。不同的哈希算法和方法可以用于不同的图像检索任务。 #### 引用[.reference_title] - *1* *3* [图像检索传统算法学习笔记](https://blog.csdn.net/qq_39858278/article/details/83895342)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [8月23日计算机视觉理论学习笔记——图像检索](https://blog.csdn.net/Ashen_0nee/article/details/126467437)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值