赞
踩
顺序结构以及平衡树中,元素关键码与其存储位置之间没有对应的关系,因此在查找一个元素时,必须要经过关键码的多次比较。顺序查找时间复杂度为O(N),平衡树中为树的高度,即O(
l
o
g
2
N
log_2 N
log2N),搜索的效率取决于搜索过程中元素的比较次数。
理想的搜索方法:可以不经过任何比较,一次直接从表中得到要搜索的元素
。
如果构造一种存储结构,通过某种函数(hashFunc)使元素的存储位置与它的关键码之间能够建立一一映射的关系
,那么在查找时通过该函数可以很快找到该元素。
这篇博客我们简单的介绍一下哈希表,重点是哈希表的实现,下次的博客会为大家详细的介绍一下哈希表。
#pragma once #include <vector> template<class K> struct Hash { size_t operator()(const K& key) { return key; } }; template<> struct Hash<string> { size_t operator()(const string& s) { size_t value = 0; for (auto& ch : s) { value += ch; } return value; } }; namespace LinearDetectionHash { enum status { EMPTY,//空 EXIST,//存在 DELETE//删除 }; template<class K, class V> struct HashData { pair<K, V> _kv;//要存的值 status _status = EMPTY;//状态 }; template<class K,class V,class HashFunc = Hash<K>> class HashTable { public: HashTable() {} bool Erase(const K& key) { HashData<K, V>* ret = Find(key); if (ret) { ret->_status = DELETE; _size--; return true; } else { return false; } } HashData<K, V>* Find(const K& key) { if (_tables.size() == 0) { return nullptr; } HashFunc hf; size_t index = hf(key) % _tables.size(); while (_tables[index]._status == EXIST) { if (_tables[index]._kv.first == key && _tables[index]._status == EXIST) { return &_tables[index]; } index++; } return nullptr; } bool Insert(const pair<K,V>& kv) { HashData<K, V>* ret = Find(kv.first); HashFunc hf; if (ret) { return false; } if (_tables.size() == 0 || _size*10 / _tables.size() > 7) { size_t newsize = _tables.size() == 0 ? 10 : 2 * _tables.size(); HashTable<K,V> newHT; newHT._tables.resize(newsize); for (int i = 0; i < _tables.size(); i++) { if (_tables[i]._status == EXIST) { newHT.Insert(_tables[i]._kv); } } _tables.swap(newHT._tables); } size_t index = hf(kv.first) % _tables.size(); while (_tables[index]._status == EXIST) { index++; index %= _tables.size(); } _tables[index]._kv = kv; _tables[index]._status = EXIST; _size++; return true; } private: vector<HashData<K,V>> _tables; size_t _size = 0; }; void TestHashTable1() { HashTable<int, int> kv; kv.Insert(make_pair(1, 1)); kv.Insert(make_pair(2, 2)); kv.Insert(make_pair(3, 3)); kv.Insert(make_pair(4, 4)); kv.Insert(make_pair(14, 14)); kv.Insert(make_pair(24, 24)); kv.Insert(make_pair(34, 34)); kv.Insert(make_pair(11, 11)); kv.Insert(make_pair(21, 21)); kv.Insert(make_pair(31, 31)); kv.Insert(make_pair(32, 32)); /*cout << kv.Find(1) << endl; cout << kv.Find(3) << endl; cout << kv.Find(14) << endl; cout << kv.Find(32) << endl; cout << kv.Find(33) << endl;*/ } void TestHashTable2() { HashTable<string, string> kv; kv.Insert(make_pair("sort", "排序")); kv.Insert(make_pair("soda", "苏打水")); kv.Erase("sort"); cout << kv.Find("sort") << endl; cout << kv.Find("test") << endl; } } namespace SecondaryDetectionHash { enum status { EMPTY, EXIST, DELETE }; template<class K, class V> struct HashData { pair<K, V> _kv; status _status = EMPTY; }; template<class K, class V, class HashFunc = Hash<K>> class HashTable { public: HashTable() {} bool Erase(const K& key) { HashData<K, V>* ret = Find(key); if (ret) { ret->_status = DELETE; _size--; return true; } else { return false; } } HashData<K, V>* Find(const K& key) { if (_tables.size() == 0) { return nullptr; } HashFunc hf; size_t i = 0; size_t index = hf(key) % _tables.size(); while (_tables[index]._status == EXIST) { if (_tables[index]._kv.first == key && _tables[index]._status == EXIST) { return &_tables[index]; } i++; index += i*i; index %= _tables.size(); } return nullptr; } bool Insert(const pair<K, V>& kv) { HashData<K, V>* ret = Find(kv.first); HashFunc hf; if (ret) { return false; } if (_tables.size() == 0 || _size * 10 / _tables.size() > 7) { size_t newsize = _tables.size() == 0 ? 10 : 2 * _tables.size(); HashTable<K, V> newHT; newHT._tables.resize(newsize); for (int i = 0; i < _tables.size(); i++) { if (_tables[i]._status == EXIST) { newHT.Insert(_tables[i]._kv); } } _tables.swap(newHT._tables); } size_t i = 0; size_t index = hf(kv.first) % _tables.size(); while (_tables[index]._status == EXIST) { i++; index += i * i; index %= _tables.size(); } _tables[index]._kv = kv; _tables[index]._status = EXIST; _size++; return true; } private: vector<HashData<K, V>> _tables; size_t _size = 0; }; void TestHashTable1() { HashTable<int, int> kv; kv.Insert(make_pair(1, 1)); kv.Insert(make_pair(2, 2)); kv.Insert(make_pair(3, 3)); kv.Insert(make_pair(4, 4)); kv.Insert(make_pair(14, 14)); kv.Insert(make_pair(24, 24)); kv.Insert(make_pair(34, 34)); kv.Insert(make_pair(11, 11)); kv.Insert(make_pair(21, 21)); kv.Insert(make_pair(31, 31)); kv.Insert(make_pair(32, 32)); cout << kv.Find(1) << endl; cout << kv.Find(3) << endl; cout << kv.Find(14) << endl; cout << kv.Find(32) << endl; cout << kv.Find(33) << endl; } void TestHashTable2() { HashTable<string, string> kv; kv.Insert(make_pair("sort", "排序")); kv.Insert(make_pair("soda", "苏打水")); //kv.Erase("sort"); cout << kv.Find("sort") << endl; cout << kv.Find("test") << endl; } } namespace LinkHash { template<class K, class V> struct HashNode { pair<K, V> _kv; HashNode<K, V>* next; HashNode(const pair<K,V>& kv) :_kv(kv) ,next(nullptr) {} }; template<class K, class V,class HashFunc = Hash<K>> class HashTable { typedef HashNode<K, V> Node; public: bool Erase(const K& key) { if (_size == 0) { return false; } HashFunc hf; size_t index = hf(key) % _tables.size(); Node* cur = _tables[index]; Node* prev = nullptr; while (cur) { if (cur->_kv.first == key) { Node* next = cur->next; if(prev) prev->next = next; else _tables[index] = next; delete cur; cur = nullptr; _size--; return true; } else { prev = cur; cur = cur->next; } } return false; } Node* Find(const K& key) { if (_size == 0) { return nullptr; } HashFunc hf; size_t index = hf(key) % _tables.size(); Node* cur = _tables[index]; while (cur) { if (cur->_kv.first == key) { return cur; } else { cur = cur->next; } } return nullptr; } bool Insert(const pair<K, V>& kv) { Node* ret = Find(kv.first); if (ret) { return false; } if (_tables.size() == 0 || _size*10 / _tables.size() == 10) { size_t newsize = _tables.size() == 0 ? 10 : 2 * _tables.size(); HashTable<K, V> newHT; newHT._tables.resize(newsize); HashFunc hf; for (int i = 0; i < _tables.size(); i++) { Node* cur = _tables[i]; while (cur) { Node* next = cur->next; size_t index = hf(cur->_kv.first) % newHT._tables.size(); if (newHT._tables[index]) { Node* next = newHT._tables[index]; newHT._tables[index] = cur; cur->next = next; } else { newHT._tables[index] = cur; newHT._tables[index]->next = nullptr;; } newHT._size++; cur = next; } _tables[i] = nullptr; } _tables.swap(newHT._tables); } HashFunc hf; Node* cur = new Node(kv); size_t index = hf(kv.first) % _tables.size(); if (_tables[index]) { Node* next = _tables[index]; _tables[index] = cur; cur->next = next; } else { _tables[index] = cur; } _size++; return true; } private: vector<Node*> _tables; size_t _size = 0; }; void TestHashTable1() { HashTable<int, int> kv; kv.Insert(make_pair(1, 1)); kv.Insert(make_pair(2, 2)); kv.Insert(make_pair(3, 3)); kv.Insert(make_pair(4, 4)); kv.Insert(make_pair(14, 14)); kv.Insert(make_pair(24, 24)); kv.Insert(make_pair(34, 34)); kv.Insert(make_pair(11, 11)); kv.Insert(make_pair(21, 21)); kv.Insert(make_pair(31, 31)); kv.Insert(make_pair(32, 32)); kv.Insert(make_pair(10, 10)); cout << kv.Find(1) << endl; cout << kv.Find(100) << endl; } void TestHashTable2() { HashTable<int, int> kv; kv.Insert(make_pair(1, 1)); kv.Insert(make_pair(11, 11)); kv.Insert(make_pair(2, 2)); cout << kv.Erase(4) << endl; cout << kv.Erase(11) << endl; cout << kv.Erase(2) << endl; cout << kv.Erase(1) << endl; } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。