哈希表
先说哈希表散列函数的设计有几种
- 直接定址法(一般没啥用,消耗空间太大了)
- 除留余数法(一般来说是除以质数,因为质数只有本身和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 }