HASH演算法的簡單實現及測試
阿新 • • 發佈:2019-01-18
一.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
- #pragma once
- #define NULL 0
- //簡化版hash_table
- //by MoreWindows( http://blog.csdn.net/MoreWindows )
-
struct
- {
- int val;
- Node *next;
- Node(int n)
- {
- this->val = n;
- this->next = NULL;
- }
- };
- class hash_table
- {
- public:
- hash_table(constint ntablesize);
- ~hash_table();
- bool insert(int n);
-
void insert(int *pFirst,
- bool find(int n);
- int size();
- int HashFun(int n);
- public:
- int m_nTableSize;
- int m_nTableDataCount;
- Node** m_ppTable;
- };
2.hash_table.cpp
- //簡化版hash_table
- //by MoreWindows( http://blog.csdn.net/MoreWindows )
- #include "hash_table.h"
- #include <malloc.h>
- #include <memory.h>
- hash_table::hash_table(constint ntablesize)
- {
- m_nTableSize = ntablesize;
- m_ppTable = (Node**)malloc(sizeof(Node*) * m_nTableSize);
- if (m_ppTable == NULL)
- return ;
- m_nTableDataCount = 0;
- memset(m_ppTable, 0, sizeof(Node*) * m_nTableSize);
- }
- hash_table::~hash_table()
- {
- free(m_ppTable);
- m_ppTable = NULL;
- m_nTableDataCount = 0;
- m_nTableSize = 0;
- }
- intinline hash_table::HashFun(int n)
- {
- return (n ^ 0xdeadbeef) % m_nTableSize;
- }
- int hash_table::size()
- {
- return m_nTableDataCount;
- }
- bool hash_table::insert(int n)
- {
- int key = HashFun(n);
- //在該連結串列中查詢該數是否已經存在
- for (Node *p = m_ppTable[key]; p != NULL; p = p->next)
- if (p->val == n)
- returntrue;
- //在連結串列的頭部插入
- Node *pNode = new Node(n);
- if (pNode == NULL)
- returnfalse;
- pNode->next = m_ppTable[key];
- m_ppTable[key] = pNode;
- m_nTableDataCount++;
- returntrue;
- }
- bool hash_table::find(int n)
- {
- int key = HashFun(n);
- for (Node *pNode = m_ppTable[key]; pNode != NULL; pNode = pNode->next)
- if (pNode->val == n)
- returntrue;
- returnfalse;
- }
- void hash_table::insert(int *pFirst, int *pLast)
- {
- for (int *p = pFirst; p != pLast; p++)
- this->insert(*p);
- }
3.main.cpp
在main.cpp中,對set、hash_set、簡化版hash_table作一個性能測試,測試環境為Win7+VS2008的Release設定(下同)。
- //測試set,hash_set及簡化版hash_table
- // by MoreWindows( http://blog.csdn.net/MoreWindows )
- #include <set>
- #include <hash_set>
- #include "hash_table.h"
- #include <iostream>
- #include <ctime>
- #include <cstdio>
- #include <cstdlib>
- usingnamespace std;
- usingnamespace stdext; //hash_set
- void PrintfContainerElapseTime(char *pszContainerName, char *pszOperator, long lElapsetime)
- {
- printf("%s 的 %s操作 用時 %d毫秒\n", pszContainerName, pszOperator, lElapsetime);
- }
- // MAXN個數據 MAXQUERY次查詢
- constint MAXN = 5000000, MAXQUERY = 5000000;
- int a[MAXN], query[MAXQUERY];
- int main()
- {
- printf("set VS hash_set VS hash_table(簡化版) 效能測試\n");
- printf("資料容量 %d個 查詢次數 %d次\n", MAXN, MAXQUERY); <