搜尋引擎中快取(cache)用到的雜湊(hash)演算法
阿新 • • 發佈:2019-01-25
前一段查看了關於雜湊的各種演算法,發現流傳最廣的還算偉大的暴雪(dota愛好者)工程師得到的一種演算法,有很多部落格中都有對其的介紹,我在此就不多廢話了。
雖說是借鑑,也只是一小部分的抄襲。不知道是否冒犯了暴雪的版權。
我修改成了我需要的功能,我的目標是對6w資料進行雜湊計算然後暫存到記憶體中,當做快取使用。這是搜尋引擎中必須要做的一步,當然,程式碼是公司機密,我只是把我寫的程式碼雛形拿出來,看看有沒有值得批評指正的地方。
小弟不才,在這6w的測試資料中,使用5倍的記憶體,得到最長的一串連結串列長達180.(不知道大家知道不知道我說的是什麼意思)。溝通的機會來了。。。。。
歡迎到之類來溝通交流:
還是看看程式碼:
#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; }