除留余数法+ 链地址再散列
#include<bits/stdc++.h>
#define HASHSIZE 13
using namespace std;
typedef struct node
{
int num;
struct node *next;
}NODE;
typedef struct hash
{
NODE *element[HASHSIZE];
int count;
}HashTable;
void Init(HashTable *p)
{
for (int i = 0; i < HASHSIZE; ++i)
{
p->element[i] = (NODE*)malloc(sizeof(NODE)*HASHSIZE);
p->element[i]->next = NULL;
}
}
// 除留余数法
int HASH(int key)
{
return key%HASHSIZE;
}
//插入元素
void InsertHash(HashTable *p, int key)
{
int addr = HASH(key);
//头插法
NODE *q = (NODE*)malloc(sizeof(NODE));
q->num = key;
q->next = p->element[addr]->next;
p->element[addr]->next = q;
}
int Search(HashTable *p, int key)
{
int addr = HASH(key);
NODE *m = p->element[addr]->next;
while (m != NULL)
{
if (m->num == key)
return addr;
m = m->next;
}
return -1;
}
int main(void)
{
int a[10] = { 12,45,2,6,78,9,0,1,15 };
HashTable table;
Init(&table);
for (int i = 0; i < 100; i++)
{
if((i%10)%3==0)continue;
InsertHash(&table,i);
}
int rq;
cout<<"输入需要查找的数字:"<<endl;
cin>>rq;
int res = Search(&table, rq);
if (res!=-1)
cout <<"查找成功!地址为: "<<res<<endl;
else
cout <<"查找失败! "<<endl;
return 0;
}
哈希时取模一定要模质数吗?
以下内容转自知乎:HTTPS://www.zhihu.com/question/20806796/answer/159392465
排除人为制造的数据外,对质数取模的优势在哪里呢?
假设N = kn,M = km,N和M存在最大公因数k,此时可以将N%M = r转化为公式N = Mq + r,即kn = kmq + r。其中q是商,r是余数。“表面上” r的取值范围是{0,1,2,...,M-1}(忽视了只有N与M最大公因数为1时,才能取整个余数集合R的定理) ,一片和谐。但是可以对公式进行稍微的变换,n = mq +(r / k),由于n和mq都是整数,则(r / k)也是整数。此时我们看一看到(r / k)的取值范围是{0,1,2,...,m} = {0,1,2,...,M / k}。恢复到原式,也是就r的“实际”取值范围是{0,k,2 * k,3 * k,...,m * k},缩小了k倍。
一切都明了了,我们最后的目标就是保证ň与中号最大公因数为1,最简单的方式就是直接取中号为质数!
再发一道哈希的模板题:
#include<iostream>
#include<cstdio>
#include<string>
#include<string.h>
using namespace std;
#define M 1046527 //一个很大的质数大于h2
#define NIL (-1)
#define L 14
char H[M][L];
//将字符串转为数字
int getChar(char a)
{
if(a=='A')return 1;
else if(a=='T')return 2;
else if(a=='C')return 3;
else if(a=='G')return 4;
else return 0;
}
long long getKey(char a[])
{
long long sum = 0,p = 1,i;
for(i = 0; i < strlen(a); i++)
{
sum+=p*(getChar(a[i]));
p*=5;
}
return sum;
}
int h1(int key){ return key%M;}
int h2(int key){return 1+(key%(M-1));}
int find(char a[])
{
long long key,h;
key = getKey(a);//将字符串转为整数
for(int i = 0;;i++)
{
h = (h1(key)+i*h2(key)) % M;
if(strcmp(H[h],a)==0) return 1;
else if(strlen(H[h])==0) return 0;
}
}
int insert(char str[])
{
long long key,h;
key = getKey(str);
for(int i = 0; ;i++)
{
h = (h1(key)+i*h2(key)) % M;
if(strcmp(H[h],str)==0) return 1;
else if(strlen(H[h])==0) { strcpy(H[h],str);return 0;}
}
}
int main()
{
int n,h;
char str[L],com[L];
for(int i = 0; i<M; i++) H[i][0]='\0';
scanf("%d",&n);
for(int i = 0; i<n; i++)
{
scanf("%s %s",com,str);
if(com[0]=='f')
if(find(str))printf("YES\n");
else printf("NO\n");
else
insert(str);
}
}