HashTable
本文主要讲解了基于拉链方式的hashTable的实现。
1、hashTable介绍
hashTable主要是用来保存一系列的键值对A={(key1,value1),(key2, value2),...,(keyn, valuen)}。hashTable的需要一个哈希函数将键值对A中的key1,key2,...,keyn进行映射,将其映射到一个固定大小的Array内(如下表达式)。映射后的index表示位于Array中的第几个元素。
然而,不幸的是,通常不同的key可能会被hashFunc映射到同一个index下面,这种现象称为冲突。重用的解决冲突的方法是:用另一种方式再映射、线性探测、拉链存储。本文主要讲解拉链存储方式。
所谓的拉链存储方式即,当两个不同的key通过同一个hashFunc映射到相同index时,将采用链表的方式将这两个键值链接起来。如下图所示。
2、代码实现
本文采用模板的方法实现了一个hashTable类。具体代码参考如下。
// HashTable.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <iostream> #include <vector> #include <list> #include <string> using namespace std; // hash 函数(根据字符串长度映射到哈希表中) static unsigned int hashFunc(const string& str, unsigned int bucketSize) { return (str.size() % bucketSize); } template<typename V> struct NODE { string key; V value; NODE* next; NODE() { next = NULL; } }; template<typename V> class hashTable { public: hashTable() { } ~hashTable() { destroyBuckets(); } public: hashTable(unsigned int size) { pFunc = hashFunc; m_buckets.clear(); m_bucketSize = size; initialBuckets(); } private: unsigned int (*pFunc)(const string& str, unsigned int bucketSize); // 哈希函数指针 unsigned int m_bucketSize; // 哈希函数中的桶的数量 vector<NODE <V>* > m_buckets; // 存储指针 void initialBuckets(); void destroyBuckets(); public: void put(const string& key, V value) { NODE<V> *node = new NODE<V>(); node->key = key; node->value = value; node->next = NULL; unsigned int index = (*pFunc)(key, m_bucketSize); NODE<V> *pCur = m_buckets[index]; NODE<V> *pPre = pCur; while(pCur->next != NULL) { pPre = pCur->next; pCur = pCur->next; } pCur->next = node; } bool get(const string& key, V& value) { unsigned int index = (*pFunc)(key, m_bucketSize); NODE<V> *pCur = m_buckets[index]; while(pCur->next != NULL) { if(key == pCur->next->key) { value = pCur->next->value; return true; } pCur = pCur->next; } return false; } }; template<typename V> void hashTable<V>::initialBuckets() { for(unsigned int i = 0; i < m_bucketSize; i++) { NODE <V>* pHead = new NODE<V>(); pHead->next = NULL; m_buckets.push_back(pHead); // 保存头指针 } } template<typename V> void hashTable<V>::destroyBuckets() { vector<NODE <V>* >::iterator iter = m_buckets.begin(); for(; iter != m_buckets.end(); iter++) { NODE<V>* pHead = *iter; while(pHead != NULL) // 从vector中的第一个元素才是释放 { NODE<V>* pCur = pHead; pHead = pHead->next; delete pCur; } } } int _tmain(int argc, _TCHAR* argv[]) { // 创建一个带10个桶的hash对象 hashTable<int> hash(10); hash.put("zhangsan", 101); hash.put("lisi", 110); hash.put("wangwu", 90); int score1, score2, score3; hash.get("zhangsan", score1); hash.get("lisi", score2); hash.get("wangwu", score3); cout<<"zhangsan' score is:"<<score1<<endl; cout<<"lisi' score is:"<<score2<<endl; cout<<"wangwu's score is:"<<score3<<endl; system("pause"); return 0; }