1. 程式人生 > >HASH演算法的簡單實現及測試

HASH演算法的簡單實現及測試

一.hash_set之基石——雜湊表

    hash_set的底層資料結構是雜湊表,因此要深入瞭解hash_set,必須先分析雜湊表。雜湊表是根據關鍵碼值(Key-Value)而直接進行訪問的資料結構,它用雜湊函式處理資料得到關鍵碼值,關鍵碼值對應表中一個特定位置再由應該位置來訪問記錄,這樣可以在時間複雜性度為O(1)內訪問到資料。但是很有可能出現多個數據經雜湊函式處理後得到同一個關鍵碼——這就產生了衝突,解決衝突的方法也有很多,各大資料結構教材及考研輔導書上都會介紹大把方法。這裡採用最方便最有效的一種——鏈地址法,當有衝突發生時將具同一關鍵碼的資料組成一個連結串列。下圖展示了鏈地址法的使用:

二.簡化版的hash_table

    按照上面的分析和圖示,並參考《程式設計珠璣》第15章中雜湊表的實現,不難寫出一個簡單的雜湊表,我們稱之為簡化版hash_table。該雜湊表由一個指標陣列組成,陣列中每個元素都是連結串列的表頭指標,程式分為hash_table.h,hash_table.cpp和main.cpp。

1.hash_table.h

  1. #pragma once
  2. #define NULL 0
  3. //簡化版hash_table 
  4. //by MoreWindows( http://blog.csdn.net/MoreWindows )
  5. struct
     Node  
  6. {  
  7.     int val;  
  8.     Node *next;  
  9.     Node(int n)  
  10.     {  
  11.         this->val = n;  
  12.         this->next = NULL;  
  13.     }  
  14. };  
  15. class hash_table  
  16. {  
  17. public:  
  18.     hash_table(constint ntablesize);  
  19.     ~hash_table();  
  20.     bool insert(int n);  
  21.     void insert(int *pFirst, 
    int *pLast);  
  22.     bool find(int n);  
  23.     int  size();  
  24.     int HashFun(int n);  
  25. public:  
  26.     int      m_nTableSize;  
  27.     int      m_nTableDataCount;  
  28.     Node**   m_ppTable;  
  29. };  

2.hash_table.cpp

  1. //簡化版hash_table
  2. //by MoreWindows( http://blog.csdn.net/MoreWindows )
  3. #include "hash_table.h"
  4. #include <malloc.h>
  5. #include <memory.h>
  6. hash_table::hash_table(constint ntablesize)  
  7. {  
  8.     m_nTableSize = ntablesize;  
  9.     m_ppTable = (Node**)malloc(sizeof(Node*) * m_nTableSize);  
  10.     if (m_ppTable == NULL)  
  11.         return ;  
  12.     m_nTableDataCount = 0;  
  13.     memset(m_ppTable, 0, sizeof(Node*) * m_nTableSize);  
  14. }  
  15. hash_table::~hash_table()  
  16. {  
  17.     free(m_ppTable);  
  18.     m_ppTable = NULL;  
  19.     m_nTableDataCount = 0;  
  20.     m_nTableSize = 0;  
  21. }  
  22. intinline hash_table::HashFun(int n)   
  23. {  
  24.     return (n ^ 0xdeadbeef) % m_nTableSize;  
  25. }  
  26. int hash_table::size()  
  27. {  
  28.     return m_nTableDataCount;  
  29. }  
  30. bool hash_table::insert(int n)  
  31. {  
  32.     int key = HashFun(n);  
  33.     //在該連結串列中查詢該數是否已經存在
  34.     for (Node *p = m_ppTable[key]; p != NULL; p = p->next)  
  35.         if (p->val == n)  
  36.             returntrue;  
  37.     //在連結串列的頭部插入
  38.     Node *pNode = new Node(n);  
  39.     if (pNode == NULL)  
  40.         returnfalse;  
  41.     pNode->next = m_ppTable[key];  
  42.     m_ppTable[key] = pNode;  
  43.     m_nTableDataCount++;  
  44.     returntrue;  
  45. }  
  46. bool hash_table::find(int n)  
  47. {  
  48.     int key = HashFun(n);  
  49.     for (Node *pNode = m_ppTable[key]; pNode != NULL; pNode = pNode->next)  
  50.         if (pNode->val == n)  
  51.             returntrue;  
  52.     returnfalse;  
  53. }  
  54. void hash_table::insert(int *pFirst, int *pLast)  
  55. {  
  56.     for (int *p = pFirst; p != pLast; p++)  
  57.         this->insert(*p);  
  58. }  

3.main.cpp

 在main.cpp中,對set、hash_set、簡化版hash_table作一個性能測試,測試環境為Win7+VS2008的Release設定(下同)。

  1. //測試set,hash_set及簡化版hash_table
  2. // by MoreWindows( http://blog.csdn.net/MoreWindows )
  3. #include <set>
  4. #include <hash_set>
  5. #include "hash_table.h"
  6. #include <iostream>
  7. #include <ctime>
  8. #include <cstdio>
  9. #include <cstdlib>
  10. usingnamespace std;  
  11. usingnamespace stdext;  //hash_set
  12. void PrintfContainerElapseTime(char *pszContainerName, char *pszOperator, long lElapsetime)  
  13. {  
  14.     printf("%s 的 %s操作 用時 %d毫秒\n", pszContainerName, pszOperator, lElapsetime);  
  15. }  
  16. // MAXN個數據 MAXQUERY次查詢
  17. constint MAXN = 5000000, MAXQUERY = 5000000;  
  18. int a[MAXN], query[MAXQUERY];  
  19. int main()  
  20. {  
  21.     printf("set VS hash_set VS hash_table(簡化版) 效能測試\n");  
  22.     printf("資料容量 %d個 查詢次數 %d次\n", MAXN, MAXQUERY);  
  23. <