hash海量資料查詢的一個實現 :周末練手

來源:互聯網
上載者:User

       前言:閑來蛋疼,周末在家陪老婆,中午還要親自操廚,操廚之前,加深下對hash的理解,寫下此篇。

       本文:本篇文章主要類比了海量搜尋過程。從txt檔案擷取大量資料資訊(類比海量),建立hash表,然後輸入關鍵字(字串),能迅速定位要找的value。其實就是搜尋某個特定的字串。具體會貼出代碼,和驗證圖。整個過程類比了海量尋找的過程,能切實感覺到hash 海量處理的優勢。

     先貼幾張運行:

                                                                                                                        

                                                                                    圖 1

        稍微解釋一下:結合圖1 中的第一行,  第359次,指發生映射的順序數;992處,指雜湊數組中的位置,即hashTable[992];存入的字串,為我們雜湊映射以後把原字串存起來,以便尋找時比較;value,指映射後要定位的值,比如:我們要尋找字串出現的機率,或是字串出現的次數等等,在程式裡相當於留了一個借口。注意:所有的資料從txt裡讀取,而txt裡的的資料由程式類比產生,採用rand()函數。具體見後面的程式源碼或下載後面貼出的工程檔案的。我產生的是5000個,通過修改宏參數,可以更多,非常貼近真實。

   

                                                                                      

                                                                           圖 2

       圖 2 最後一行,顯示了要尋找字串的位置。如,藍色部分。

  

 

      網上先搜尋了一番,發現要麼就是理論一堆,要麼就是貼出關鍵代碼,讓我等菜鳥始終沒法體會海量的涵義。

      本文章分為三大部分。第一部分:hash的基本知識,第二部分,hash映射的建立和衝突的解決,具體代碼實現

       hash 的主要作用就是快速尋找,其時間複雜度是O(1),是最好的尋找演算法。對於hash的入門層級可參考我的一篇其他博文 資料結構-練習2 雜湊表。hash的最基本理解就是:根據要尋找的字串的ASCII(經過變換處理),通過雜湊函數,轉換成與其儲存位置的下標,這樣在hash表建立以後,我們就可以根據字串本身,以相同的雜湊函數映射方式迅速定位到其位置,然後尋找出相關資訊。
 雜湊函數的構造就成為了最重要的任務之一,常見的方法有:直接取址法,平方取中法,除留餘數法,數字分析法,摺疊法,隨機數法。

本文章的例子採用除留餘數法:

                                                                              基本原理為:H(key)=key%MOD,MOD 為小於表長的一個數,本例子為1024.

結合代碼具體分析(SDBM法):

                              

int SDBMHash(char* str)    {        int hash = 0;        while(*str!='\0')       { 
          //相當於:65599*hash+*str++,這就是映射函數,通過字串裡每個字元的ASCIIl累計形成          hash = *str++ + (hash << 6) + (hash << 16) - hash;       }        return (hash & 0x7FFFFFFF);    }

最後別忘了求餘數:key=key%HashTableLen;//HashTableLen=1024,key就是SDBMHash的傳回值。

衝突解決是第二個重要的過程,基本方法包括:鏈表法,開放地址法,再雜湊,開闢公用溢出區。

本文章例子採用常見的鏈表法:

                                                                                                                              

,左邊為:第一次獲得的key的位置,顯然,兩個不同的字串很可能有相同的key,這時我們在後面加個鏈表格儲存體一下。

代碼如:

                 

 p=&HashT[key];while(p->next!=NULL) p=p->next;{p->next=new hashNode();p->next->used=true;strcpy(p->next->key,str);p->next->value=rand()%100;
        }

   貼完整個程式的代碼:

             

#include<iostream>#include<fstream>#include<string>using namespace std;const unsigned int NUM=5000;const int HashTableLen=1024;int count=0;//用於記錄hash映射時,發生的次數,驗證作用struct hashNode {bool used;hashNode* next;char  key[28];unsigned int value;hashNode(){used=false;next=NULL;}hashNode(char* KEY,unsigned int VALUE){strcpy(key,KEY);value=VALUE;}}HashT[HashTableLen] ;// 雜湊表的長度為1024,所以取摸的時候用1024;unsigned int elfhash(char* s);//declare the functionvoid createStrTXT();void establishHaT();void  FindStr(char*);int main(){    //for(int i=0;i<50000;++i) //產生txt,檔案,往裡面隨機寫入字串。   //createStrTXT();  establishHaT();    FindStr("qd`e_usigh]oscfwsnfreshayug");    //FindStr(); /* char str[30];  ifstream ifs("str.txt");  ifs>>str;  */} int SDBMHash(char* str)    {        int hash = 0;        while(*str!='\0')       {          hash = *str++ + (hash << 6) + (hash << 16) - hash;       }        return (hash & 0x7FFFFFFF);    }unsigned int elfhash(char *s){    int hash = 0, x = 0;    while (*s){        hash = (hash << 4) + (*s++);        if(((x = hash) & 0xf0000000L) != 0){            hash ^= (x >> 24);            hash &= ~x;        }    }    return hash & 0x7fffffff;}void createStrTXT(){for(int i=0;i<NUM;++i){char temp[30]={'\n','\r',rand()%31+91,rand()%31+91,rand()%31+91,rand()%31+91,rand()%31+91,rand()%31+91,rand()%31+91,rand()%31+91,rand()%31+91,rand()%31+91,rand()%31+91,rand()%31+91,rand()%31+91,rand()%31+91,rand()%31+91,rand()%31+91,rand()%31+91,rand()%31+91,rand()%31+91,rand()%31+91,rand()%31+91,rand()%31+91,rand()%31+91,rand()%31+91,rand()%31+91,rand()%31+91,rand()%31+91,'\0'};         char*str=temp;        ofstream ofs("str.txt",ios::app);        ofs<<str;}}void  establishHaT()//採用鏈表法構造hash表{  hashNode * p;  int key;  char str[28];  ifstream ifs("str.txt");  while( ifs>>str)  {   key=SDBMHash(str);   key=key%HashTableLen;   if(HashT[key].used==false)   {   strcpy(HashT[key].key,str);   HashT[key].used=true;   HashT[key].value=rand()%100;    count++;                                                    //偽隨機的目的是類比key-value 裡的value,裡面就是我們要尋找的值,e.g. 如果要尋找字串是否存                                                               //在,   printf("第%d次在 %d處發生了映射,存入的字串為:%s,value為:%d\n",count,key,str,HashT[key].value);//裡面就村字串本身;如果要查某字串出現的機率,                                                              //裡面就是機率值,如果尋找的是字串出現的次數,裡面存的就是次數,正如百度的那道尋找top 10的                                                              //面試題,原理跟這一樣   }   else//衝突處理   {    p=&HashT[key];while(p->next!=NULL) p=p->next;{p->next=new hashNode();p->next->used=true;strcpy(p->next->key,str);p->next->value=rand()%100;count++;        printf("第%d次在 %d處發生了映射,存入的字串為:%s,value為:%d\n",count,key,str,HashT[key].value);          }         }    }  }void  FindStr(char* str){    hashNode * p;  int key;    key=SDBMHash(str);  key=key%HashTableLen;  if(HashT[key].used==false)  {    printf("此字串不存在");                                                               }  else  {     p=&HashT[key];  while(p!=NULL)  {  if(!strcmp(p->key,str))   {  printf("在%d位置處找到了目的字串:%s",key,str);  break;  }  else  {  p=p->next;  }  if(p==NULL) printf("SORRY!字串沒有匹配的");  }  }  }    
                          
說明:函數 FindStr(char*)主要是尋找特定的字串,原理與構造hash函數的過程一樣。注意的是:寫入函數參數中的字串,不應該含有轉義符,因為轉義符號,程式可能不認識,所以,在TXT裡選一個沒有轉移符號的作為參數,如本例。
createStrTXT();主要是建立txt檔案,NUM是建立的字串的個數,注意的是,我建立時,寫入檔案採用了ios::app,所以每次運行程式,如果都createStrTXT(),txt裡的字元 串個數會每次都增加5000次。所以建立一次就可以,以後就登出。工程檔案:此處下載。需要一積分,不好意思,我想攢點分下東西,沒積分的 留下郵箱。我將速度發送。

                                                                                    

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.