- 之前研究STL源码的时候发现哈希Table底层是实现看起来实现的非常的简洁,觉得自己去写一个哈希表肯定也是很简单的。但是,但是,但是我今天看了一下数据结构里面的哈希表的简单实现,才发现其实也是有很多学问在里面的,所以今天就打算自己实现一下,做一个记录,方便以后自己来查看学习。
- 因为哈希表是会产生哈希冲突的嘛,一般的解决方法都是采用开链法,所以今天就简单的实现一个开链法的具体步骤。
- 具体步骤
- 先是写一个简单的模板类的框架
#include <iostream> #include <list> #include <vector> #include <string.h> using namespace std; template <typename Object> class HashTable{ public: explicit HashTable(int hashsize = 101); bool constains(const Object & x)const; void makeEmpty(); void insert(const Object & x); void remove(const Object & x); private: int CurrentSize; vector < list<Object> > theLists;//这个是vector加上list的格式 void ReHash(); int MyHash (const Obeject & a) const; }; int hash (const string & x); int hash (int key);
这个框架还是比较通俗的,但是由于编辑工具不是很好用(linux下面的编辑工具有点bug,老是闪退,我就么有建工程,将就看吧)。主要就是实现了一下插入,删除,包含核哈希函数的构造这几个简单的方法。下面是这几个函数的具体实现代码。
-
void ReHash(){ } int MyHash (const Obeject & a) const{ int hashval = hash(x); hashval %= theLists.size(); if (hashval < 0) hashval += theLists.size(); return hashval; } void makeEmpty(){ for ( int i = 0; i< theLists.size(); i++) theLists[i].clear(); } bool insert(const Object & x){ list<Object> &list1 = theLists[ MyHash(x) ]; if (find ((list1.begin(), list1.end(), x) != list1.end())) return false; list1.push_back(x); if (++CurrentSize > theLists.size()) ReHash(); return true; } bool remove(const Object & x){ /*移除就是找到了对应的*/ list<Object> &list1 = theLists[ MyHash(x) ]; list<Object> ::iterator iter = find (list1.begin(), list1.end(), x); if ( iter == list1.end() ) return false; list1.erase(iter); --CurrentSize; return true; } bool constains(const Object & x)const{ /*这个就是相当于找到了对应的链表,再去链表中找到对应的实值*/ const list<Object> &list1 = theLists[ MyHash(x) ]; return find ((list1.begin(), list1.end(), x) != list1.end()) }
这个就是实现简单的带有链表和vector的哈希表了,这个比较常见。
- 当然还有不使用链表的哈希表。
- 这样的链表的解决冲突的方式有许多种
- 线性探测,根据键值,调用哈希函数找到对应的键值,如果该位置已经满了,就依次向后移动一个位置,知道找到末尾还是满了,就从头部开始向后找起,直到找到一个空的可以插入的位置。
- 平方探测,这个和上面类似,但是它每次移动的位置是当前移动次数的平方倍数。这个随机性比较大。
- 关于这一类的哈希表的实现我自己感觉应该是比上面的那种简单些,实现方式大多是类似的。最主要的还是去检测当前位置是否满,然后移动的规则的一些算法。
- 这样的链表的解决冲突的方式有许多种
- STL中的散列表还有一些其他类型的。比如hash_set,hash_map;感兴趣可以去看些STL源码。
- 先是写一个简单的模板类的框架