当前位置:   article > 正文

数据结构-查找-哈希表

数据结构-查找-哈希表

一、哈希表的映射方法

1、直接定址法(值的分布范围集中)

比如统计字符串中字符出现的次数,字符范围集中。

2、除留余数法(值的分布范围分散)

hashi = key % n

但是这种方法会导致,哈希冲突:不同的值映射到相同的位置

不同关键字通过相同哈希哈数计算出相同的哈希地址,该种现象称为哈希冲突
或哈希碰撞

解决哈希冲突的方案

闭散列的---开放定址法:当前位置被占用了,按规则找下一个位置(占用别人的位置)

1、线性探测

2、二次探测

.

二、查找的时候可以找的到,但是这个值在空的后面

查找逻辑:遇到空就停止查找。

可以使用状态来标记

1、EXIST

2、EMPTY

3、DELETE

查找的时候,遇到状态EMPTY才能停止。

三、哈希表什么时候扩容

散列表的载荷因子定义为 :填入表中的元素个数 /散列表的长度

负载因子越大,冲突概率越大,空间利用率越高

负载因子越小,冲突概率越小,空间利用率越低。空间浪费越多。

哈希表不能满了扩容,控制负载因子到一定值就扩容。负载因子可以限制在0.7~0.8之间。

四、扩容以后我们的映射关系就变了,需要重新映射。

解决方案:

1、 重新开一个vector,把旧的的值直接插入到新的vector里面中去。遍历旧表重新映射到新表。

2、我们可以重新搞一个hash表,把空间提前开好,遍历旧表插入到新表里。然后旧表和新表进行交换。

  1. bool Insert(const pair<K, V>& kv)
  2. {
  3. // 扩容
  4. //if ((double)_n / (double)_table.size() >= 0.7)
  5. if (_n*10 / _table.size() >= 7)
  6. {
  7. size_t newSize = _table.size() * 2;
  8. // 遍历旧表,重新映射到新表
  9. HashTable<K, V, HashFunc> newHT;
  10. newHT._table.resize(newSize);
  11. // 遍历旧表的数据插入到新表即可
  12. for (size_t i = 0; i < _table.size(); i++)
  13. {
  14. if (_table[i]._state == EXIST)
  15. {
  16. newHT.Insert(_table[i]._kv);
  17. }
  18. }
  19. _table.swap(newHT._table);
  20. }
  21. // 线性探测
  22. HashFunc hf;
  23. size_t hashi = hf(kv.first) % _table.size();
  24. while (_table[hashi]._state == EXIST)
  25. {
  26. ++hashi;
  27. hashi %= _table.size();
  28. }
  29. _table[hashi]._kv = kv;
  30. _table[hashi]._state = EXIST;
  31. ++_n;
  32. return true;
  33. }

二次探测

hashi  = key%n

hashi = key%i^2

开放定址法的缺点:冲突会互相影响。

哈希桶:

第二种方法为哈希桶

插入:

  1. bool Insert(const T& data)
  2. {
  3. // 负载因子到1就扩容
  4. if (_n == _table.size())
  5. {
  6. // 16:03继续
  7. size_t newSize = _table.size()*2;
  8. vector<Node*> newTable;
  9. newTable.resize(newSize, nullptr);
  10. // 遍历旧表,顺手牵羊,把节点牵下来挂到新表
  11. for (size_t i = 0; i < _table.size(); i++)
  12. {
  13. Node* cur = _table[i];
  14. while (cur)
  15. {
  16. Node* next = cur->_next;
  17. // 头插到新表
  18. size_t hashi = cur->_data % newSize;
  19. cur->_next = newTable[hashi];
  20. newTable[hashi] = cur;
  21. cur = next;
  22. }
  23. _table[i] = nullptr;
  24. }
  25. _table.swap(newTable);
  26. }
  27. size_t hashi = data % _table.size();
  28. // 头插
  29. Node* newnode = new Node(data);
  30. newnode->_next = _table[hashi];
  31. _table[hashi] = newnode;
  32. ++_n;
  33. return true;
  34. }

删除:

  1. bool Erase(const K& key)
  2. {
  3. size_t hashi = key % _table.size();
  4. Node* prev = nullptr;
  5. Node* cur = _table[hashi];
  6. while (cur)
  7. {
  8. if (kot(cur->_data) == key)
  9. {
  10. if (prev == nullptr)
  11. {
  12. _table[hashi] = cur->_next;
  13. }
  14. else
  15. {
  16. prev->_next = cur->_next;
  17. }
  18. --_n;
  19. delete cur;
  20. return true;
  21. }
  22. prev = cur;
  23. cur = cur->_next;
  24. }
  25. return false;
  26. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/567931
推荐阅读
相关标签
  

闽ICP备14008679号