哈希表
先说哈希表散列函数的设计有几种
- 直接定址法(一般没啥用,消耗空间太大了)
- 除留余数法(一般来说是除以质数,因为质数只有本身和1才可除,这样分布比较均匀,冲突率小)这种方法比较easy也比较常用
- 数字分析法(仅仅对那种数据量具有明显区分特征的才管用,并且要先知道有哪些数值,通常情况下数据是随机分布的)
- 平方取中法(对关键码平方后取中间几位,因为平方后中间几位比较均匀,不会堆积在一起导致散列后大量冲突,比如123*123=15129,我们可以选51也可以12)
- 折叠法(当关键码位数很多的情况下,我们可以用折叠法,)比如把12345678分成123+456+78=xxx然后再对这个数进行散列分析.
再说下处理冲突的方法
- 开放定址法,(用开放定址法得到的散列表叫闭散表)
- 线性探测法 这里对关键码去摸后的值冲突的话放到下一个空位置。很简单不多讲。直接将算法
- 这里我写了4种返回值,对不同情况都有返回。
/*返回正数表示找到的地址
返回-1表示位找到而且位置全满
返回-2表示J位置空缺,且已经把查找数插入J位置
返回-3表示J位置有冲突下,已经探测到后面空缺位置且把j插入
*/
int HashSearch(vector<int>& v,int k)//k是要查找的值,这里假设所有值都是正数,所以初始化的时候V里面全是-1.-1表示空
{
//获取散列表大小
int m=v.size();
//获取散列值
int j=H(k);
//查找一次相同情况下直接返回
if(v[j]==k)return j;
//j位置空缺时候,插入,返回-2表示
else if(v[j]==-1)
{
v[j]=k;
return -2;
}
//设置起始位置,加入再次探测到这里还没有表示没有这个数
int i=(j+1)%m;//这里%m是防止j在散列表的最后导致溢出问题
//查找多次
while(v[i]!=-1&&i!=j)
{
if(v[i]==k)return i;
else i=(i+1)%m;
}
if(i==j)
return -1;//表示没找到
else
{
v[i]=k;
return -3;//返回-3表示j位置冲突查找不成功后插入
}
}
比较常见的处理冲突的方法还有拉链法,为了快捷我们一般用头插法。
其实就是单链表的查找非常简单
直接上代码了
1 //首先解释下这个函数的输入,第一个参数是头结点的链表,第二个参数是m是表长,第三是k表示查找值
2 Node* Hashsearch(Node* ht[],int m,int k)
3 {
4 int j=H(k);//获取散列表 H要自己写
5 auto p=ht[j]; //这里就像单链表里面的auto p=first一个道理;
6 while((p!=NULL)&&(p->data!=k))
7 {
8 p=p->next;
9 }
10 if(p->data==k)return p; //假如找到了就返回这个节点
11 else //没找到就插入
12 {
13 Node* q=new Node;
14 q->data=k;
15 q->next=p->next;
16 p->next=q;
17
18 }
19 }