哈希表查找:Hash
在查找数据时需要进行一系列的比较运算,无论是顺序查找、二分查找、索引查找、这类的查找算法都是建立在比较的基础上的,但最理想的查找算法是不经过任何比较,一次存取就能查找到数据,那么就需要在存储位置和它的关键字之间建立一个确定的对应关系,使每个关键字和数据中的唯一的存储位置相对应。在查找时,根据对应关系找到给定的关键字所对应的数据,这样可以不经过比较可以直接取得所查找的数据。
我们称存储位置在关键字之间的对应关系为哈希函数,按这个思想建立的表为哈希表。
设计哈希函数的方法:
直接定值法:
取关键字的值或某个线性函数作为k哈希地址:H(key) = key 或H(key)=a*key-b,但这种方法对数据有很高的要求。
问题:假设有10000个范围在0~255之间的随机整数,请任意输入0~255之间的一个整数,帮查询该整数总共出现了多少次?
#include <stdio.h> #include <stdlib.h> int main(int argc,const char* argv[]) { int arr[10000] = {}; for(int i=0; i<10000; i++) { arr[i] = rand() % 256; } // 建立哈希表 int hash[256] = {}; // 通过直接定值法 建立哈希函数 for(int i=0; i<10000; i++) { hash[arr[i]]++; } unsigned char num = 0; printf("请输入:"); scanf("%hhu",&num); printf("次数:%d\n",hash[num]); }
时间复杂度:O(1)
但是有很大的局限性,因为很多数据是无法直接用做数组的下标的,其次可能会出现数据量少,但是数据值的差值较大,导致哈希表长度过大,造成内存浪费
数字分析法:
分析数据的特点设计哈希,常用方法是找到最大最小值,最大值-最小值+1 确定哈希表的长度,通过 数据-最小值 访问哈希表下标
以上两种方法局限比较大,但计算出的哈希地址没有冲突的可能,以下方法:平方取中法、折叠法、除留余数法等方法对关键字的要求不要,但计算出的哈希地址可能会有冲突。称为哈希冲突
解决哈希值冲突的方法:
-
开方地址法
-
再哈希法
-
链地址法
-
创建公共溢出区
哈希查找的优点:
查找速度极快,时间复杂度能达到O(1)。
哈希查找的缺点:
1、局限性比较大,对数据的要求比较高。
2、设计哈希函数麻烦,没具体的设计哈希函数的方法,只是有一些大致的思路。
3、需要建立哈希表,占用了额外的空间。
Hash函数的应用:MD5、SHA-1都属于Hash算法