示例:除留余数:对输入的数字取模。
哈希冲突:多个不同的值指向同一个位置
解决方法:
把24放在下一个位置
哈希桶
闭散列的负载因子:表元素个数/散列表长度(size),当负载因子达到一定范围时就进行扩容。
扩容会涉及重新映射,取模的范围变大了。
闭散列的元素搜索:闭散列的元素搜索到空截止,要搜索的值只可能往后延,不可能提前,所以如果为空,说明没有。
闭散列的删除:不能直接置空,而是要设置一个状态值表示是否删除。
- enum STATE
- {
- EXIST,
- EMPTY,
- DELETE
- };
对于其他类型string,可以选择仿函数来取哈希值,算法上的难点是取哈希值的方式。
其中一个算法
- template<>
- struct DefaultHashFunc
- {
- size_t operator()(const string& str)
- {
- // BKDR
- size_t hash = 0;
- for (auto ch : str)
- {
- hash *= 131;
- hash += ch;
- }
-
- return hash;
- }
- };
完整代码
- namespace myhashtable {
- enum STATE
- {
- EXIST,
- EMPTY,
- DELETE
- };
- template<class K, class V>
- struct HashData
- {
- pair
_kv; - STATE _state = EMPTY;
-
- };
- template<class K>
- struct DefaultHashFunc
- {
- size_t operator()(const K& key)
- {
- return (size_t)key;
- }
- };
- template<>
- struct DefaultHashFunc
- {
- size_t operator()(const string& str)
- {
- // BKDR
- size_t hash = 0;
- for (auto ch : str)
- {
- hash *= 131;
- hash += ch;
- }
-
- return hash;
- }
- };
-
- template<class K, class V,class HashFunc=DefaultHashFunc
> - class HashTable
- {
- public:
- HashTable()
- {
- _table.resize(10);
- }
- bool Insert(const pair
& kv) - {
- //扩容
- if ((double)_n * 10 / (double)_table.size() >= 0.7)
- {
- size_t newSize = _table.size() * 2;
- // 扩容以后映射关系变了
- HashTable
newHT; - newHT._table.resize(newSize);
- // 遍历旧表的数据插入新表就可以了
- for (size_t i = 0; i < _table.size(); i++)
- {
- if (_table[i]._state == EXIST)
- {
- newHT.Insert(_table[i]._kv);
- }
- }
- _table.swap(newHT._table);
- }
- HashFunc hf;
- size_t hashi =hf( kv.first) % _table.size();
- while (_table[hashi]._state == EXIST)
- {
- ++hashi;
- hashi %= _table.size();
- }
- _table[hashi]._kv = kv;
- _table[hashi]._state = EXIST;
- ++_n;
- return true;
- }
- HashData<const K, V>* Find(const K& key)
- {
- HashFunc hf;
- size_t hashi = hf(key) % _table.size();
- while (_table[hashi]._state != EMPTY)
- {
- if (_table[hashi]._state == EXIST
- && _table[hashi]._kv.first == key)
- {
- return (HashData<const K, V>*) & _table[hashi]._kv;
- }
- ++hashi;
- hashi %= _table.size();
- }
- return nullptr;
-
- }
- bool Erase(const K& key)
- {
- HashData<const K, V>* ret = Find(key);
- if (ret)
- {
- ret->_state = DELETE;
- --_n;
- return true;
- }
- return false;
- }
- private:
- vector
> _table; - size_t _n =0;
- };
- }
关键点:哈希表存节点地址,用单链表存冲突的哈希值
- namespace bush_bucket
- {
- template<class K,class V>
- struct HashNode
- {
- pair
_kv; - HashNode
* _next; - HashNode(const pair
kv) - {
- _kv = kv;
- _next = nullptr;
- }
- };
- template<class K,class V>
- class HashTable
- {
- typedef HashNode
Node; - public:
- HashTable()
- {
-
- _table.resize(10,nullptr);
- }
- ~HashTable()
- {
- for (size_t i= 0; i < _table.size(); i++)
- {
- Node* cur = _table[i];
- while (cur)
- {
- Node* next = cur->_next;
- delete cur;
- cur = next;
- }
- _table[i] = nullptr;
- }
- }
- bool Insert(const pair
& kv) - {
- if (Find(kv.first))
- {
- return false;
- }
- // 扩容
- if (_n == _table.size())
- {
- size_t newSize = _table.size()*2;
- vector
newTable; - newTable.resize(newSize, nullptr);
- for (size_t i = 0; i < _table.size(); i++)
- {
- Node* cur = _table[i];
- while (cur)
- {
- Node* next = cur->_next;
- size_t hashi = cur->_kv.first % newSize;
- cur->_next = newTable[hashi];
- newTable[hashi] = cur;
- cur = next;
- }
- _table[i] = nullptr;
- }
- _table.swap(newTable);
- }
- size_t hashi = kv.first % _table.size();
- Node* newnode = new Node(kv);
- newnode->_next = _table[hashi];
- _table[hashi] = newnode;
- ++_n;
- return true;
- }
- Node* Find(const K& key)
- {
- size_t hashi = key% _table.size();
- Node* cur = _table[hashi];
- while (cur)
- {
- if (cur->_kv.first == key)
- {
- return cur;
- }
-
- cur = cur->_next;
- }
- return nullptr;
- }
- bool Erase(const K& key)
- {
- size_t hashi = key % _table.size();
- Node* prev = nullptr;
- Node* cur = _table[hashi];
- while (cur)
- {
- if (cur->_kv.first == key)
- {
- if (prev == nullptr)
- {
- _table[hashi] = cur->_next;
- }
- else
- {
- prev->_next = cur->_next;
- }
- delete cur;
- return true;
- }
- prev = cur;
- cur = cur->_next;
- }
- return false;
- }
- void Print()
- {
- for (int i = 0; i < _table.size(); i++)
- {
- printf("[%d]->", i);
- Node* cur = _table[i];
- while (cur)
- {
- cout << cur->_kv.first << "->";
- cur = cur->_next;
- }
- printf("null");
- printf("\n");
- }
- }
- private:
- vector
_table; //指针数组 - size_t _n=0;
- };
- }