您的位置:首页 > 其它

搜索引擎中缓存(cache)用到的哈希(hash)算法

2013-04-26 11:21 615 查看
前一段查看了关于哈希的各种算法,发现流传最广的还算伟大的暴雪(dota爱好者)工程师得到的一种算法,有很多博客中都有对其的介绍,我在此就不多废话了。

虽说是借鉴,也只是一小部分的抄袭。不知道是否冒犯了暴雪的版权。

我修改成了我需要的功能,我的目标是对6w数据进行哈希计算然后暂存到内存中,当做缓存使用。这是搜索引擎中必须要做的一步,当然,代码是公司机密,我只是把我写的代码雏形拿出来,看看有没有值得批评指正的地方。

小弟不才,在这6w的测试数据中,使用5倍的内存,得到最长的一串链表长达180.(不知道大家知道不知道我说的是什么意思)。沟通的机会来了。。。。。

欢迎到之类来沟通交流:

http://lee-sven.com/wordpress/?p=330

还是看看代码:

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>

//#define DEBUG
#define NUM 10240	//缓存的最大数据量
typedef struct hash{
char flag;
char hz[64];
char *art;
int time;
int n;
struct hash *next;
}HASH;
HASH *hashtable1=NULL,*hashtable2=NULL,*hashtable3=NULL,*hashtable4=NULL,*hashtable5=NULL;
unsigned long cryptTable[0x500];

/******************************************************
*	函数功能:申请哈希表所用的内存;
*	函数参数:void;
*	函数输出:成功:1;失败:-1;
******************************************************/
int getMalloc(){
hashtable1 = (HASH *)malloc((NUM)*sizeof(HASH));
hashtable2 = (HASH *)malloc(NUM*sizeof(HASH));
hashtable3 = (HASH *)malloc(NUM*sizeof(HASH));
hashtable4 = (HASH *)malloc(NUM*sizeof(HASH));
hashtable5 = (HASH *)malloc(NUM*sizeof(HASH));
memset(hashtable1,0,(NUM)*sizeof(HASH));
memset(hashtable2,0,NUM*sizeof(HASH));
memset(hashtable3,0,NUM*sizeof(HASH));
memset(hashtable4,0,NUM*sizeof(HASH));
memset(hashtable5,0,NUM*sizeof(HASH));
if(hashtable1==NULL||hashtable2==NULL||hashtable3==NULL||hashtable4==NULL||hashtable5==NULL)
{
perror("get Malloc error");
return -1;
}
return 1;
}

/******************************************************
*	函数功能:生成一个长度为0x500的cryptTable[0x500];
*	函数参数:void;
*	函数输出:void;
******************************************************/
void prepareCryptTable()
{
unsigned long seed = 0x00100001, index1 = 0, index2 = 0, i;

for( index1 = 0; index1 < 0x100; index1++ )
{
for( index2 = index1, i = 0; i < 5; i++, index2 += 0x100 )
{
unsigned long temp1, temp2;

seed = (seed * 125 + 3) % 0x2AAAAB;
temp1 = (seed & 0xFFFF) << 0x10;

seed = (seed * 125 + 3) % 0x2AAAAB;
temp2 = (seed & 0xFFFF);

cryptTable[index2] = ( temp1 | temp2 );
}
}
}

/******************************************************
*	函数功能:	计算lpszFileName 字符串的hash值;
*	函数参数:	字符串指针 、运算类型(可以去0、1、2);
*	函数输出:	哈希值;
******************************************************/
unsigned long HashString( char *lpszFileName, unsigned long dwHashType )
{
unsigned char *key  = (unsigned char *)lpszFileName;
unsigned long seed1 = 0x7FED7FED;
unsigned long seed2 = 0xEEEEEEEE;
int ch;

while( *key != 0 )
{
ch = toupper(*key++);

seed1 = cryptTable[(dwHashType << 8) + ch] ^ (seed1 + seed2);
seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3;
}
return ((seed1*2654435769)%NUM);//seed1%5000
}

/******************************************************
*	函数功能:	往哈希表中对应节点的内存中写内容
*	函数参数:	ptr:哈希表中一个节点指针 str:关键词
*	函数输出:	void
******************************************************/
void writemem(HASH *ptr,char *str){
#ifdef DEBUG
static int i=0;
i++;
printf("i=%d\n",i);
#endif
#ifdef DEBUG
printf("-------writemem start--------\n");
#endif
HASH *p=ptr,*q;

while(p->next != NULL){
p=p->next;
}
#ifdef DEBUG
printf("----sizeof(HASH):%d-----\n",sizeof(HASH));
#endif
HASH *p_hash=NULL;
p_hash = (HASH *)malloc(sizeof(HASH));
memset(p_hash,0,sizeof(HASH));
#ifdef DEBUG
printf("----------1------------\n");
#endif
if(p_hash == NULL){
perror("p_hash malloc error");
}
strcpy(p_hash->hz,str);
p_hash->flag = 1;
p_hash->next=NULL;
/*此处还需加上拷贝搜索内容的代码*/
p->next=p_hash;
#ifdef DEBUG
printf("-------writemem end--------\n");
#endif
}

/******************************************************
*	函数功能:	往哈希表中写数据
*	函数参数:	n:哈希值 hz:关键字数 str:关键字
*	函数输出:	void
******************************************************/
void writeHash(int n,int hz,char *str){
#ifdef DEBUG
printf("-------writeHash start--------\n");
#endif
switch(hz){
case 1:
writemem((hashtable1+n),str);
break;
case 2:
writemem((hashtable2+n),str);
break;
case 3:
writemem((hashtable3+n),str);
break;
case 4:
writemem((hashtable4+n),str);
break;
case 5:
writemem((hashtable5+n),str);
break;
case 6:
case 7:
case 8:
case 9:
break;
default:
break;
}
#ifdef DEBUG
printf("-------writeHash end--------\n");
#endif
}

/******************************************************
*	函数功能:	遍历哈希表,查询有多少内容
*	函数参数:	void
*	函数输出:	void
******************************************************/
void countHash(){
int i;
int all=0;
for(i=0;i<NUM;i++){
HASH *p=hashtable1+i;
while(p->next!=NULL){
p=p->next;
all++;
}
p=hashtable2+i;
while(p->next!=NULL){
p=p->next;
all++;
}
p=hashtable3+i;
while(p->next!=NULL){
p=p->next;
all++;
}
p=hashtable4+i;
while(p->next!=NULL){
p=p->next;
all++;
}
p=hashtable5+i;
while(p->next!=NULL){
p=p->next;
all++;
}
}
printf("the title = %d\n",all);
}

/******************************************************
*	函数功能:	删除哈希表中某一个节点上的内容
*	函数参数:	ptr:哈希节点指针 str:关键字
*	函数输出:	找到删除的节点并正确删除返回1;否则返回0
******************************************************/
char deletemem(HASH *ptr,char *str){
HASH *p=ptr,*q;
while(p!=NULL){
if(strcmp(p->hz,str) == 0){
q->next=p->next;
/*此处还需加上释放存放搜索结果内存的代码*/
free(p);
return 1;
}
q=p;
p=p->next;
}
printf("delet fail\n");
return 0;
}

/******************************************************
*	函数功能:	往哈希节点
*	函数参数:	n:哈希值 hz:关键字数 str:关键字
*	函数输出:	void
******************************************************/
void deleteNode(int n,int hz,char *str){
#ifdef DEBUG
printf("-------delete start--------\n");
#endif
switch(hz){
case 1:
deletemem((hashtable1+n),str);
break;
case 2:
deletemem((hashtable2+n),str);
break;
case 3:
deletemem((hashtable3+n),str);
break;
case 4:
deletemem((hashtable4+n),str);
break;
case 5:
deletemem((hashtable5+n),str);
break;
case 6:
case 7:
case 8:
case 9:
break;
default:
break;
}
#ifdef DEBUG
printf("-------delete end--------\n");
#endif
}

int main(){
int error=0;
int flag=1,count=0;
unsigned long ulHashValue;
char *hzString=(char *)malloc(256);
if(hzString==NULL){
perror("hzString malloc error");
}
error = getMalloc();
if(error==-1){
perror("malloc hash error");
//暂时不做处理
}
FILE *stream,*fdata;
fdata=fopen("data.txt","w+");
stream=fopen("test.txt","r+");
srand((int)time(NULL));
while(1){
int hz=0;
while(hz == 0)
hz=((unsigned int)rand())%5;
char ch[4];
int i;
for(i=0;i<hz;i++){
memset(ch,0,sizeof(ch));
ch[0] = fgetc(stream);
if(ch[0]==EOF){
flag=0;
break;
}
if(ch[0] < 0){
ch[1] = fgetc(stream);
if(ch[1] == EOF){
flag=0;
break;
}
}
strcat(hzString,ch);
}
count++;
if(flag==0||count>NUM)
break;
prepareCryptTable();
ulHashValue = HashString(hzString,0);
char p[20];
memset(p,0,20);
sprintf(p,"%u\n",(unsigned int)ulHashValue);
fwrite(p,1,strlen(p),fdata);
#ifdef DEBUG
printf("ulHashValue=%u\n",(unsigned int)ulHashValue);
#endif
writeHash(ulHashValue,hz,hzString);
if(count%5==0){
deleteNode(ulHashValue,hz,hzString);
}
memset(hzString,0,256);
}
#ifdef DEBUG
#endif
countHash();

free(hzString);
fclose(fdata);
fclose(stream);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: