本篇博客将利用 C++ 中的 类 对哈希结构的底层进行代码实现!且在本篇程序实现中,将基于开散列(开链法)利用二次探测实现对哈希冲突的解决!并基于实现的哈希结构,对map和set 进行了模拟实现!
代码中涉及了哈希、map、set等实现,并附带了实例以及对应的运行结果!
具体内容如下main.cpp
#includeusing namespace std; #include #include enum STATE { EXIST, DELETE, EMPTY }; //哈希表:此代码文件中哈希冲突所使用处理方法:二次探测,开散列(开链法) -- 哈希桶 template struct HashNode { V _val; HashNode * _next; HashNode(const V& val) :_val(val) , _next(nullptr) {} }; template struct HashFun { size_t operator()(const K& key) { return key; } }; template <> // 特化,将插入的string数据的key转换为int struct HashFun { size_t operator()(const string& key) { size_t hash = 0; for (const auto& ch : key) { hash = hash * 131 + ch; } return hash; } }; //哈希表的前置声明 template > class HTable; //哈希表迭代器:自定义类型 //通过封装单链表的节点实现 template > struct HashIterator { typedef HashIterator Self; typedef HTable HT; //成员:节点指针,哈希表指针 typedef HashNode Node; HT* _hPtr; Node* _node; HashIterator(Node* node, HT* hptr) :_node(node) , _hPtr(hptr) {} V& operator*() { return _node->_val; } V* operator->() { return &_node->_val; } bool operator!=(const Self& it) { return _node != it._node; } Self& operator++() { if (_node->_next) _node = _node->_next; else { //查找下一个非空链表的头节点 //计算当前节点在哈希表中的地址 KeyofValue kov; HashFun hfun; int idx = hfun(kov(_node->_val)) % _hPtr->_ht.size(); ++idx; for (; idx < _hPtr->_ht.size(); ++idx) { if (_hPtr->_ht[idx]) { _node = _hPtr->_ht[idx]; break; } } //没有有效节点 if (idx == _hPtr->_ht.size()) { _node = nullptr; } } return *this; } }; template > class HTable { public: typedef HashNode Node; typedef HashIterator iterator; //把迭代器声明为友元类 --> 如此HashIterator就可访问HTable的私有成员 template friend struct HashIterator; HTable(int n = 10) :_ht(n) , _size(0) {} iterator begin() { //返回第一个非空链表的头节点 for (int i = 0; i < _ht.size(); ++i) { if (_ht[i]) { return iterator(_ht[i], this); } } return iterator(nullptr, this); } iterator end() { //返回一个空的迭代器位置 return iterator(nullptr, this); } //利用 除留余数法 实现对系统的增容! size_t GetNextPrime(size_t prime) { const int PRIMECOUNT = 28; const size_t primeList[PRIMECOUNT] = { 53ul, 97ul, 193ul, 389ul, 769ul, 1543ul, 3079ul, 6151ul, 12289ul, 24593ul, 49157ul, 98317ul, 196613ul, 393241ul, 786433ul, 1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul, 50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul, 1610612741ul, 3221225473ul, 4294967291ul }; size_t i = 0; for (; i < PRIMECOUNT; ++i) { if (primeList[i] > primeList[i]) return primeList[i]; } return primeList[i - 1]; } void checkCapacity() { if (_size == _ht.size()) { int newC = _size == 0 ? 10 : 2 * _size; //size_t newC = GetNextPrime(_ht.size()); //创建新的指针数组 vector newHt(newC); cout << newHt.size() << endl; KeyofValue kov; HashFun hfun; //遍历旧表 for (int i = 0; i < _ht.size(); ++i) { Node* cur = _ht[i]; while (cur) { Node* next = cur->_next; //计算新的位置 int idx = hfun(kov(cur->_val)) % newHt.size(); //头插 cur->_next = newHt[idx]; newHt[idx] = cur; cur = next; } //旧表指针置空 _ht[i] = nullptr; } //新表与旧表交换 swap(_ht, newHt); //swap(_size, newHt); } } pair insert(const V& val) { //0、检查容量 checkCapacity(); //1、计算hash位置 KeyofValue kov; HashFun hfun; int idx = hfun(kov(val)) % _ht.size(); //2、查找 Node* cur = _ht[idx]; while (cur) { if (kov(cur->_val) == kov(val)) return make_pair(iterator(cur, this), false); cur = cur->_next; } //3、插入:头插 cur = new Node(val); cur->_next = _ht[idx]; _ht[idx] = cur; ++_size; return make_pair(iterator(cur, this), true); } private: //指针数组 vector _ht; int _size; }; template class Map { struct MapKeyofValue { const K& operator()(const pair & val) { return val.first; } }; public: typedef typename HTable , MapKeyofValue>::iterator iterator; V& operator[](const K& key) { //iterator 指的是所返回元素在链表中的位置 pair ret = _ht.insert(make_pair(key, V())); return ret.first->second; } iterator begin() { return _ht.begin(); } iterator end() { return _ht.end(); } pair insert(const pair & val) { return _ht.insert(val); } private: HTable , MapKeyofValue> _ht; }; template class Set { struct SetKeyOfValue { const K& operator()(const K& key) { return key; } }; public: //此 HTable , MapKeyOfValue> 中可以不用给第四个泛型,因为上面将其设置为缺省泛型了 //当然可直接写为 HTable -- 这和缺省的功能一样 typedef typename HTable ::iterator iterator; iterator begin() { return _ht.begin(); } iterator end() { return _ht.end(); } bool insert(const K& key) { _ht.insert(key); return true; } private: //此 HTable , MapKeyOfValue> 中可以不用给第四个泛型,因为上面将其设置为缺省泛型了 HTable _ht; }; void test() { Set s; s.insert(1); s.insert(2); s.insert(3); s.insert(4); s.insert(11); s.insert(22); s.insert(33); s.insert(44); s.insert(31); s.insert(41); s.insert(24); s.insert(8); Set ::iterator it = s.begin(); while (it != s.end()) { cout << *it << " "; ++it; }cout << endl; for (auto& e : s) { cout << e << " "; }cout << endl; } int main() { test(); system("pause"); return 0; }
test函数中案例的运行结果
(1)map的案例
(2)set的案例



