哈希表
哈希表的主要作用是把一个非常大的集合映射到一个比较小的集合中,
建立哈希表需要一个hash函数,一般的操作就是取模;
许多个非常大的数字对一个比较小的数字取模之后容易发生冲突,也就是
容易出现重复;
常用的解决冲突的方法有拉链法,
1.拉链法,就是在对应的hash值下面接一个链表,链表中存储的是原来的数字。
链表建议使用数组实现的链表;
例如将一些非常大的数字存储在一个大小为1e5的数组中,(建立hash表时,取模的数字最好是质数,这样可以降低出现冲突的概率)
具体操作:
哈希表使用数组实现,下标就是对应的哈希值,下标所表示的值当作链表的头节点,插入一个数相当于在链表的头部插入一个数
const int N=100003;//取质数;
int h[N],e[N],ne[N],idx;
memset(h,-1,sizeof h)//头节点初始化为-1;
//数组链表//e[N]表示具体存储的值,ne[N]表示链表存储的下一个位置的下标;
void insert(int x){//插入操作
int k=(x%N+N)%N;//考虑到会出现负数的情况(cpp中负数取模为负数),哈希函数;
e[idx]=x;//数组实现的链表,在头节点插入;
ne[idx]=h[k];
h[k]=idx++;//
}
bool find(int x){//查找操作;
int k=(x%N+N)%N;//找到哈希值;
for(int i=h[k];i!=-1;i=ne[i])//遍历链表查找
if(e[i]==x) return true;
return false;
}
2.开放寻址法
基本原理:
建立一个数组(一般这个数组大小为数据范围的2~3倍)这样可以避免冲突。
然后找到对应的哈希值,然后看这个位置是否存储元素,如果已经存储了元素则依次往后寻找,直到某个位置为空的时候,将这个值存储下来;
核心操作为寻找对应可存储这个值的位置;
//开放寻址法:
const int N=200003,null=0x3f3f3f3f;
//memset(h,0x3f,sizeof h);全部初始化为null;
int find(int x){
int k=(x%N+N)%N;//哈希值
while(h[k] != null and h[k]!=x){//寻找对应位置;
k++;
if(k==N) k=0;//找到结尾没找到之后从头开始找
}
return k;
}//这个函数有两种意义,1.哈希表中已经存在x,找到了x对应的下标并返回
//2.找到了一个空位适合存储x,并且返回这个位置的下标;
字符串哈希 ,(未完)