哈希表(Hash Table),又称散列表,是一种能够快速处理插入和查询操做的数据结构。哈希表体现着函数映射的思想,它将数据与其存储位置经过某种函数联系起来,其在查询时的高效性也体如今这里。换言之,咱们创建一个函数关系(称之为散列函数):data—>address,将数据和其存储位置关联;查询时,咱们只须要根据咱们创建的函数关系就能经过data查询到address。html
可见,散列函数的创建直接影响着哈希表的效率。当咱们的散列函数创建得足够优时,哈希表在插入和查询上的时间复杂度都能被降为O(1)。经常使用的创建散列函数的方法有以下几种:node
一、直接寻址法:直接取数据或数据的某种线性函数做为散列函数;算法
二、平方取中法:对数据平方,取其中间几位做为散列函数;数据结构
三、折叠法:将数据拆开成几部分,再从新组合;ide
四、除留取余法:用数据对一个大质数取模,将余数做为散列函数。 函数
本篇blog采用除留取余法创建散列函数。spa
显然,因为函数是一种容许多个自变量对应同一应变量的关系,在插入和查询时,存储位置的冲突便不可避免。当发生冲突时,咱们一般用如下两种方法解决:code
一、错位法:即当正在读入的数据与之前已经插入表中的数据冲突时,咱们从发生冲突的存储位置开始向某个方向寻找一个空存储位置,将当前读入的数据插入其中;htm
二、拉链法:结合链表的思想,将全部相互发生冲突的数据拉成一条链。blog
哈希表的优势很明显,就是它在插入和查询室常数级别的时间复杂度。然而它的缺点也很明显,包括没法存储相同的元素,没法排序,并且极占用空间。因此想要熟练运用哈希表也不是一件容易的事情,下面咱们不妨看一道模板题。
给出n个正整数,而后有m个询问,每一个询问一个整数,询问该整数是否在n个正整数中出现过。
第一行两个整数 n 和m。
第二行n个正整数(1<=n<= 100000)
第三行m个整数(1<=m<=100000)
一共m行,若出现则输出YES,不然输出NO
4 2
2 1 3 4
1 9
YES
NO
全部数据都不超过10^8
附上原题连接→_→|1230 元素查找|CODEVS,算法爱好者社区
1 #include<stdio.h> 2 #define MAX 100010 3 #define p 10000007 4 int n,m; 5 struct node 6 { 7 int next; 8 int data; 9 }; 10 int st[p],cnt; 11 node tab[MAX]; 12 int ans; 13 int getHashAddress(int x){return x%p;}//散列函数 14 void insert(int x)//插入元素 15 { 16 int address=getHashAddress(x); 17 for(int i=st[address];i;i=tab[i].next)//判断元素是否在表中 18 if(tab[i].data==x)return; 19 tab[++cnt].next=st[address];//拉链 20 st[address]=cnt; 21 tab[cnt].data=x; 22 } 23 bool find(int x)//查询元素 24 { 25 int address=getHashAddress(x); 26 for(int i=st[address];i;i=tab[i].next) 27 if(tab[i].data==x)return true; 28 return false; 29 } 30 int main() 31 { 32 scanf("%d%d",&n,&m); 33 for(int i=1;i<=n;++i) 34 { 35 int x; 36 scanf("%d",&x); 37 insert(x); 38 } 39 for(int i=1;i<=m;++i) 40 { 41 int x; 42 scanf("%d",&x); 43 if(find(x))printf("YES"); 44 else printf("NO"); 45 printf("\n"); 46 } 47 return 0; 48 }
弱弱地说一句,本蒟蒻码字也不容易,转载请注明出处http://www.cnblogs.com/Maki-Nishikino/p/5999356.html