小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

C 實現(xiàn)哈希表 HashMap沖突鏈式解決

 閑來看看 2013-02-25

C++實現(xiàn)哈希表 HashMap沖突鏈式解決

簡述:

考慮到有大量數(shù)據(jù)的情況,所以使用Hash表

使用泛型實現(xiàn)

TypeA 是Key的類型,TypeB 是value的類型


1. 主要函數(shù)

1). TypeB Put(HashNode<TypeA,TypeB> 函數(shù)用來加入一個新的MapNode

2). TypeB Delete(const TypeA& key) 用來刪除一個鍵值為key的節(jié)點

3). TypeB GetValue(const  TypeA& key) 通過key值來搜尋他的value


2. 主要算法

1) 使用一個函數(shù)類型指向用戶定義的哈希值計算函數(shù),這里我用了GetKeyValue_1這個平方取中法

2)使用鏈式法解決沖突,首先是一個節(jié)點指針數(shù)組,table[index] ,其中index是哈希函數(shù)計算出來的

如果由于鍵值傳入哈希函數(shù)后計算出同一個index值,那么就以table[index]為頭節(jié)點,橫向建立鏈表避免沖突


3.類實現(xiàn)以及測試代碼

HashMap.cpp


  1. ///***************************HashMap****************************/  
  2. //1.用數(shù)組形式建立哈希表  
  3. //2.使用鏈式方法解決沖突  
  4. //3.平方取中法通過字符串Hash函數(shù)求hash值(還有很多種其他的hash函數(shù))  
  5. #include <iostream>  
  6. #include <string>  
  7. #include <cstring>  
  8. #include <stdlib.h>  
  9. #include <time.h>  
  10.   
  11. using namespace std;  
  12.   
  13. typedef unsigned long(*GetKeyValue)(const string& );  
  14.   
  15. //該類用來處理沖突的節(jié)點  
  16. template<class TypeA,class TypeB>  
  17. struct HashNode{  
  18.     TypeA key;  
  19.     TypeB value;  
  20.     HashNode *next;  
  21.     HashNode(TypeA key,TypeB value){  
  22.         HashNode::key = key;  
  23.         HashNode::value = value;  
  24.         next = NULL;  
  25.     }  
  26.     HashNode& operator=(const HashNode& node){  
  27.         key = node.key;  
  28.         value = node.key;  
  29.         next = node.next;  
  30.         return *this;  
  31.     }  
  32. };  
  33.   
  34.   
  35. //該類是HashMap用來存放hash表  
  36. template<class TypeA,class TypeB,class FuncType>  
  37. class HashMap{  
  38.     HashNode<TypeA,TypeB> **table;  
  39.     unsigned long capacity;  
  40.     FuncType GetKeyValue;  
  41.     const TypeB TYPEB_NULL;  
  42. public:  
  43.     HashMap(FuncType func,const TypeB& _null);  
  44.     ~HashMap();  
  45.     TypeB Put(const HashNode<TypeA,TypeB>& hashNode);  //插入一個HashNode 返回該節(jié)點的value值  
  46.     TypeB GetValue(const TypeA& key);  // 查找某個hashNode 其key為“key“的元素  
  47.     TypeB Delete(const TypeA& key);  // 查找某個hashNode 其key為“key“的元素  
  48. };  
  49.   
  50.   
  51. template<class TypeA,class TypeB,class FuncType> //在調(diào)用的時候指定函數(shù)  
  52. HashMap<TypeA,TypeB,FuncType>::HashMap(FuncType func,const TypeB& _null) : TYPEB_NULL(_null){  
  53.     capacity = 10000000;  
  54.     GetKeyValue = func;  
  55.     table = new HashNode<TypeA,TypeB>*[capacity];  
  56.     for(unsigned i = 0;i < capacity;i++)  
  57.         table[i] = NULL;  
  58. }  
  59.   
  60.   
  61. template<class TypeA,class TypeB,class FuncType>  
  62. HashMap<TypeA,TypeB,FuncType>::~HashMap(){  
  63.     for(unsigned i = 0;i < capacity;i++){  
  64.         HashNode<TypeA,TypeB> *currentNode = table[i];  
  65.         while(currentNode){  
  66.             HashNode<TypeA,TypeB> *temp = currentNode;  
  67.             currentNode = currentNode->next;  
  68.             delete temp;  
  69.         }  
  70.     }  
  71. }  
  72.   
  73.   
  74. //新增節(jié)點操作,用鏈式法解決衝突  
  75. template<class TypeA,class TypeB,class FuncType>  
  76. TypeB HashMap<TypeA,TypeB,FuncType>::Put(const HashNode<TypeA,TypeB>& hashNode){  
  77.     HashNode<TypeA,TypeB> *newNode = NULL;  
  78.     unsigned long index = GetKeyValue(hashNode.key);  
  79.     if(table[index] == NULL){  
  80.         table[index] = new HashNode<TypeA,TypeB>(hashNode.key,hashNode.value);  
  81.         newNode = table[index];  
  82.     }  
  83.     else{  
  84.         newNode = table[index];  
  85.         while(newNode->next){  
  86.             newNode = newNode->next;  
  87.         }  
  88.         newNode->next = new HashNode<TypeA,TypeB>(hashNode.key,hashNode.value);  
  89.         newNode = newNode->next;  
  90.     }  
  91.     return newNode->value;  
  92. }  
  93.   
  94.   
  95. //由鍵值獲得value  
  96. template<class TypeA,class TypeB,class FuncType>  
  97. TypeB HashMap<TypeA,TypeB,FuncType>::GetValue(const TypeA& key){  
  98.     unsigned long index = GetKeyValue(key);  
  99.     if(table[index] == NULL)  
  100.         return TYPEB_NULL;  
  101.     else{  
  102.         HashNode<TypeA,TypeB> *currentNode = table[index];  
  103.         while(currentNode){  
  104.             if(currentNode->key == key)  
  105.                 return currentNode->value;  
  106.             currentNode = currentNode->next;  
  107.         }  
  108.     }  
  109.     return TYPEB_NULL;  
  110. }  
  111.   
  112.   
  113. //由鍵值查找后,刪除該節(jié)點,返回該刪除的節(jié)點的value  
  114. template<class TypeA,class TypeB,class FuncType>  
  115. TypeB HashMap<TypeA,TypeB,FuncType>::Delete(const TypeA& key){  
  116.     TypeB deletedNodeValue = TYPEB_NULL;  
  117.     unsigned long index = GetKeyValue(key);  
  118.     if(table[index] == NULL)  
  119.         return deletedNodeValue;  
  120.     else{  
  121.         HashNode<TypeA,TypeB> *currentNode = table[index];  
  122.         if(currentNode->key == key){  
  123.             table[index] = currentNode->next;  
  124.             deletedNodeValue = currentNode->value;  
  125.             delete currentNode;  
  126.             return deletedNodeValue;  
  127.         }  
  128.         while(currentNode){  
  129.             if(currentNode->next->key == key){  
  130.                 HashNode<TypeA,TypeB> *temp = currentNode->next;  
  131.                 currentNode->next = currentNode->next->next;  
  132.                 deletedNodeValue = temp->value;  
  133.                 delete temp;  
  134.                 return deletedNodeValue;;  
  135.             }  
  136.             currentNode = currentNode->next;  
  137.         }  
  138.     }  
  139.     return deletedNodeValue;  
  140. }  
  141.   
  142.   
  143.   
  144. /***************************************測試****************************/  
  145. //平方取中法  
  146. //實現(xiàn),取字符串中間3個字母,不足3個用0補足  
  147. unsigned long GetKeyValue_1(const string& key){  
  148.     unsigned long keyValue = 0;  
  149.     int strSize = key.size();  
  150.     string tempStr(key);  
  151.     for(int i = strSize;i < 3;i++)  
  152.         tempStr = "0" + tempStr;  
  153.     //如果大于3就取中間3位  
  154.     if(strSize >= 3){  
  155.         tempStr[0] = key[strSize / 2 - 1];  
  156.         tempStr[1] = key[strSize / 2];  
  157.         tempStr[2] = key[strSize / 2 + 1];  
  158.     }  
  159.     tempStr = tempStr.substr(0,3);  
  160.     unsigned long num = 10000 * (unsigned long)(48);  
  161.     num += 100 * (unsigned long)(tempStr[1]);  
  162.     num += (unsigned long)(tempStr[2]);  
  163.     num *= num;  
  164.     char *numStr = new char[15];  
  165.     numStr = itoa(num,numStr,10) ;  
  166.     int strLen = strlen(numStr);  
  167.     tempStr = "000000";  
  168.     for(int i = -2;i < 4;i++)  
  169.         tempStr[2 + i] = numStr[strLen / 2 + i];  
  170.     keyValue = atoi(tempStr.c_str());  
  171.   
  172.     delete []numStr;  
  173.     return keyValue;  
  174. }  
  175.   
  176. int main(){  
  177.     clock_t start = clock();  
  178.     //傳入一個求哈希散列值的方法GetKeyValue_1  
  179.     HashMap<string,string,GetKeyValue> hashMap(GetKeyValue_1,"NULL");  
  180.     for(int i = 0;i < 100000;i++){  
  181.         char *ckey = new char[20];  
  182.         char *cvalue = new char[20];  
  183.         ckey = itoa(i,ckey,10);  
  184.         cvalue = itoa(i,cvalue,10);  
  185.         string key(ckey);  
  186.         string value(cvalue);  
  187.         if(i == 67){  
  188.             key = "67";  
  189.             value = "hello hash No.67";  
  190.         }  
  191.         HashNode<string,string> node1(key,value);  
  192.         //插入該節(jié)點  
  193.         hashMap.Put(node1);  
  194. //        cout << "index: " <<GetKeyValue_1(key) << " nodeValue: "  
  195. //             << hashMap.Put(node1) << endl;  
  196.   
  197.     }  
  198.     clock_t end = clock();  
  199.     cout << "Test Result: \n";  
  200.     //調(diào)用了time.h文件的CLOCKS_PER_SEC,表示每過千分之一秒,clock()函數(shù)返回值加1  
  201.     cout << "插入100000條數(shù)據(jù)耗時: "  
  202.          << double(end - start) / CLOCKS_PER_SEC << " 秒" << endl;  
  203.     cout << "hashMap.GetValue(\"67\"): " << hashMap.GetValue("67") << endl;  
  204.     cout << "hashMap.Delete(\"67\"): " << hashMap.Delete("67") << endl;  
  205.     cout << "hashMap.GetValue(\"67\"): " << hashMap.GetValue("67") << endl;  
  206.     return 0;  
  207. }  




測試輸出:

1) 函數(shù)測試

這里選用的是插入一萬條的結(jié)果,測試函數(shù)是否正確。

每次新增、刪除、搜索一個節(jié)點,就輸出該節(jié)點的value值。

發(fā)現(xiàn)index為67的先加入后來成功刪除,就輸出了NULL


2) 性能測試:

插入10萬條數(shù)據(jù)時間:

插入100萬條:

插入1000萬條:


    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多