程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 哈希表的C++實現(轉),哈希

哈希表的C++實現(轉),哈希

編輯:C++入門知識

哈希表的C++實現(轉),哈希


哈希表的幾個概念:

映像:由哈希函數得到的哈希表是一個映像。

沖突:如果兩個關鍵字的哈希函數值相等,這種現象稱為沖突。

處理沖突的幾個方法:

1、開放地址法:用開放地址處理沖突就是當沖突發生時,形成一個地址序列,沿著這個序列逐個深測,直到找到一個“空”的開放地址,將發生沖突的關鍵字值存放到該地址中去。

例如:hash(i)=(hash(key)+d(i)) MOD m (i=1,2,3,......,k(k<m-1)) d為增量函數,d(i)=d1,d2,d3,...,dn-1

根據增量序列的取法不同,可以得到不同的開放地址處理沖突探測方法。

有線性探測法、二次方探測法、偽隨機探測法。

2、鏈地址法:把所有關鍵字為同義詞的記錄存儲在一個線性鏈表中,這個鏈表成為同義詞鏈表,即把具有相同哈希地址的關鍵字值存放在同義鏈表中。

3、再哈希表:費時間的一種方法

下面是代碼:

文件"myhash.h"

 

Cpp代碼 
  1. #include<iostream>  
  2. using namespace std;  
  3.   
  4. typedef int KeyType; //設關鍵字域為整形,需要修改類型時,只需修改這裡就可以  
  5. const int NULLKEY=0; //NULLKEY表示該位置無值  
  6. int c=0; //用來統計沖突次數  
  7.   
  8. struct Elemtype //數據元素類型  
  9. {  
  10.     KeyType key;  
  11.     int ord;   
  12. };  
  13.   
  14. int hashsize[]={11,19,29,37,47}; //hash表容量遞增表  
  15. int Hash_length=0;//hash表表長  
  16.   
  17. class HashTable  
  18. {  
  19. private:  
  20.     Elemtype *elem; //數據元素數組,動態申請  
  21.     int count;// 當前數據元素個數  
  22.     int size; //決定hash表的容量為第幾個,hashsize[size]為當前hash容量  
  23. public:  
  24.   
  25.     int Init_HashTable() //構造一個空hash表  
  26.     {  
  27.         int i;  
  28.         count=0;  
  29.         size=0; //初始化容量為hashsize[0]=11  
  30.         Hash_length=hashsize[0];  
  31.         elem=new Elemtype[Hash_length];  
  32.         if(!elem)  
  33.         {  
  34.             cout<<"內存申請失敗"<<endl;  
  35.             exit(0);  
  36.         }  
  37.         for(i=0;i<Hash_length;i++)  
  38.             elem[i].key=NULLKEY;  
  39.         return 1;  
  40.     }  
  41.   
  42.     void Destroy_HashTable()  
  43.     {  
  44.         delete[]elem;  
  45.         elem=NULL;  
  46.         count=0;  
  47.         size=0;  
  48.     }  
  49.   
  50.     unsigned Hash(KeyType k) //hash函數的一種(取模法)  
  51.     {  
  52.         return k%Hash_length;  
  53.     }  
  54.   
  55.     void Collision(int &p,int d) //解決沖突  
  56.     {  
  57.         p=(p+d)%Hash_length; //采用開放地址法裡的線性探測  
  58.     }  
  59.   
  60.     bool Search_Hash(KeyType k,int &p) //查找  
  61.     {  
  62.         //在開放地址hash表中查找關鍵字等於k的元素  
  63.         //若找到用p表示待查數據,查找不成功時,p指向的是可插入地址  
  64.         c=0;  
  65.         p=Hash(k); //求hash地址  
  66.         while(elem[p].key!=NULLKEY && elem[p].key!=k)  
  67.         {  
  68.             c++;  
  69.             if(c<Hash_length)  
  70.                 Collision(p,c);  
  71.             else  
  72.                 return 0; //表示查找不成功  
  73.         }  
  74.         if(elem[p].key==k)  
  75.             return 1;  
  76.         else  
  77.             return 0;  
  78.   
  79.     }  
  80.   
  81.     int Insert_Hash(Elemtype e) //插入  
  82.     {  
  83.         //在查找不成功的情況下將k插入到hash表中  
  84.         int p;  
  85.         if(Search_Hash(e.key,p))  
  86.             return -1; //表示該元素已在hash表中  
  87.         else if(c<hashsize[size]/2) //沖突次數未達到上限  
  88.         {  
  89.             //插入e  
  90.             elem[p]=e;  
  91.             count++;  
  92.             return 1;  
  93.         }  
  94.         else  
  95.             ReCreate_HashTable(); // 重建hash表  
  96.         return 0; //插入失敗  
  97.     }  
  98.   
  99.     void ReCreate_HashTable() //重建hash表  
  100.     {  
  101.         int i,count2=count;  
  102.         Elemtype *p,*elem2=new Elemtype[count];  
  103.         p=elem2;  
  104.         cout<<"____重建hash表_____"<<endl;  
  105.         for(i=0;i<Hash_length;i++) //將原有元素暫存到elem2中  
  106.             if(elem[i].key!=NULLKEY)  
  107.                 *p++=*(elem+i);  
  108.         count=0;  
  109.         size++; //hash容量增大  
  110.         Hash_length=hashsize[size];  
  111.         p=new Elemtype[Hash_length];  
  112.         if(!p)  
  113.         {  
  114.             cout<<"空間申請失敗"<<endl;  
  115.             exit(0);  
  116.         }  
  117.         elem=p;  
  118.         for(i=0;i<Hash_length;i++)  
  119.             elem[i].key=NULLKEY;  
  120.         for(p=elem2;p<elem2+count2;p++) //將原有元素放回新表  
  121.             Insert_Hash(*p);  
  122.     }  
  123.   
  124.     void Traverse_HashTable()  
  125.     {  
  126.         cout<<"哈希地址0->"<<Hash_length-1<<endl;  
  127.         for(int i=0;i<Hash_length;i++)  
  128.             if(elem[i].key!=NULLKEY)  
  129.                 cout<<"元素的關鍵字值和它的標志分別是:"<<elem[i].key<<"  "<<elem[i].ord<<endl;  
  130.   
  131.     }  
  132.   
  133.     void Get_Data(int p)  
  134.     {  
  135.         cout<<"元素的關鍵字值和它的標志分別是:"<<elem[p].key<<"  "<<elem[p].ord<<endl;  
  136.     }  
  137.       
  138. };  

測試函數"main.cpp"

 

 

 

Cpp代碼 
  1. #include"myhash.h"  
  2.   
  3. int main()  
  4. {  
  5.     Elemtype r[12]={{17,1},{60,2},{29,3},{38,4},{1,5},{2,6},{3,7},{4,8},{5,9},{6,10},{7,11},{8,12}};  
  6.     HashTable H;  
  7.     int i,p,j;  
  8.     KeyType k;  
  9.     H.Init_HashTable();  
  10.     for(i=0;i<11;i++) //插入前11個記錄  
  11.     {  
  12.         j=H.Insert_Hash(r[i]);  
  13.         if(j==-1)  
  14.             cout<<"表中已有關鍵字為"<<r[i].key<<"  "<<r[i].ord<<"的記錄"<<endl;  
  15.     }  
  16.   
  17.     cout<<"按哈希地址順序遍歷哈希表"<<endl;  
  18.     H.Traverse_HashTable();  
  19.     cout<<endl;  
  20.   
  21.     cout<<"輸入要查找的記錄的關鍵字:";  
  22.     cin>>k;  
  23.     j=H.Search_Hash(k,p);  
  24.     if(j==1)  
  25.         H.Get_Data(p);  
  26.     else  
  27.         cout<<"無此記錄"<<endl;  
  28.   
  29.     j=H.Insert_Hash(r[11]); //插入最後一個元素  
  30.     if(j==0)  
  31.     {  
  32.         cout<<"插入失敗"<<endl;  
  33.         cout<<"需要重建哈希表才可以插入"<<endl;  
  34.         cout<<"____重建哈希表____"<<endl;  
  35.         H.Insert_Hash(r[i]); //重建後重新插入  
  36.     }  
  37.   
  38.     cout<<"遍歷重建後的哈希表"<<endl;  
  39.     H.Traverse_HashTable();  
  40.     cout<<endl;  
  41.   
  42.     cout<<"輸入要查找的記錄的關鍵字:";  
  43.     cin>>k;  
  44.     j=H.Search_Hash(k,p);  
  45.     if(j==1)  
  46.         H.Get_Data(p);  
  47.     else  
  48.         cout<<"該記錄不存在"<<endl;  
  49.   
  50.     cout<<"____銷毀哈希表____"<<endl;  
  51.     H.Destroy_HashTable();  
  52.   
  53.     return 0;  
  54. }  

測試結果:

 

 

 

Cpp代碼 
  1. 按哈希地址順序遍歷哈希表  
  2. 哈希地址0->10  
  3. 元素的關鍵字值和它的標志分別是:5  9  
  4. 元素的關鍵字值和它的標志分別是:1  5  
  5. 元素的關鍵字值和它的標志分別是:2  6  
  6. 元素的關鍵字值和它的標志分別是:3  7  
  7. 元素的關鍵字值和它的標志分別是:4  8  
  8. 元素的關鍵字值和它的標志分別是:60  2  
  9. 元素的關鍵字值和它的標志分別是:17  1  
  10. 元素的關鍵字值和它的標志分別是:29  3  
  11. 元素的關鍵字值和它的標志分別是:38  4  
  12. 元素的關鍵字值和它的標志分別是:6  10  
  13. 元素的關鍵字值和它的標志分別是:7  11  
  14.   
  15. 輸入要查找的記錄的關鍵字:5  
  16. 元素的關鍵字值和它的標志分別是:5  9  
  17. ____重建hash表_____  
  18. 插入失敗  
  19. 需要重建哈希表才可以插入  
  20. ____重建哈希表____  
  21. 遍歷重建後的哈希表  
  22. 哈希地址0->18  
  23. 元素的關鍵字值和它的標志分別是:38  4  
  24. 元素的關鍵字值和它的標志分別是:1  5  
  25. 元素的關鍵字值和它的標志分別是:2  6  
  26. 元素的關鍵字值和它的標志分別是:3  7  
  27. 元素的關鍵字值和它的標志分別是:4  8  
  28. 元素的關鍵字值和它的標志分別是:5  9  
  29. 元素的關鍵字值和它的標志分別是:60  2  
  30. 元素的關鍵字值和它的標志分別是:6  10  
  31. 元素的關鍵字值和它的標志分別是:7  11  
  32. 元素的關鍵字值和它的標志分別是:8  12  
  33. 元素的關鍵字值和它的標志分別是:29  3  
  34. 元素的關鍵字值和它的標志分別是:17  1  
  35.   
  36. 輸入要查找的記錄的關鍵字:7  
  37. 元素的關鍵字值和它的標志分別是:7  11  
  38. ____銷毀哈希表____  
  39. Press any key to continue  

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved