一.定义
哈希表是一种数据结构,它使用散列函数将数据存储在数组中,并使用哈希值快速查找数据。哈希表可以帮助我们快速插入、查找和删除数据,时间复杂度为O(1),因此它是一种非常高效的数据结构。哈希表通常用于实现数据缓存、字典和其他数据存储方案。(来源于ChitGPT)
二.制表
(1)十进制辅助理解
当我们拿到十进制数时,可以表达为这样
198=1*100+9*10+8;他的位权值分别为:100,10,1;
11451=1*+1*
+4*
+5*
+1*
那为什么我们要乘以位权值呢?
因为十进制数不乘以位权值的话就是这样了:
678=6+7+8=21;
579=5+7+9=21;
那么21是表达678?还是579?
如果我们乘以位权值就可以巧妙的化解这个矛盾了。
(2)字符串
让我们回忆一下ASCII:
当我们看到97是就可以想到‘a’;
当我们看到100时就可以想到‘d’;
那么‘ad’怎么表示呢?
难道是97+100=197?但'bc'怎么表示呢?还是98+99=197。
那么197表示'bc'?还是'ad'?
这时我们就要想到上面的位权值思想了;
若有26个字母,我们把位权值定义为int B=26;
当拿到'ad'时就可以表达为97*+100*
=2622;
'bc'=98*+99*
=2647;
这样我们就能保证没有重复了,2622也只能表示为'ad'。
(3)用函数表达
定义s='abcd';和h[]数组。
可以定义成这样:
const int B=26;
char a[4]={0,'a','b','c'};
int h[4];
for(int i=1;i<=strlen(a);i++){
h[i]=h[i-1]*B+a[i];
}
三.查找
(1)十进制辅助理解
我们知道当有一个数:114时,如果我们想拿到14就可以114-1*=14;
123456,我们想拿到456时就可以123456-123*=456;
这样我们可以总结出结论:
定义十进制数(非字符串,只是用abc表示)abcde,要求cd,因为len(cd)=2;
则cd=abcd-ab*
即abcd-ab*
ps:如果不理解可以自己画一画看看。
(2)字符串
先定义进制 int B=26;
当拿到‘abcde’,让我们求'de'的话:'abcde'-'abc'*
其他和十进制数一样,只是进制的区别
我们可以总结出规律:
定义字符串'abcde'当要求'cd'时就:
strlen(cd)=2;
'cd'='abcd'-'ab'*
即:'cd'='abcd'-'ab'*
(3)用函数表达
当总字符串是string s=0"abcd"; //0要把下标0的位置占了
求子字符串"cd"时:
len=cd.length()=2
"cd"=h[5]-h[5-len]*
即"cd"=h[5]-h[3]*
四.哈希冲突
(1)定义
指的是当两个或多个不同的数据具有相同的哈希值时发生的现象
(2)举个栗子
int(max)=2147483647;
int(min)=-2147483628;
所以2174783648超界会自动转换为-2147483648;
那么-2147483648不超界时也是-2147483648;
那么-2147483648是表达哪一个呢?
所以这就是hash冲突。
(3)解决方案
当我们把2个大数分别取模两个互质的数AB,这样得到的数ansa1,ansa2和ansb1,ansb2一定ansa1!=ansb1&&ansa2==ansb2,这样就巧妙的解决了hash冲突。(至于为什么要这样取模是数学领域研究的问题,可以记住结论就行)
一般我们分别取模1e9+7和1e9+9
具体应用见下一期:hash表的应用
五.总结
hash是处理字符串问题中不可缺少的元素,具体应用见下一期:hash表的应用