目录

1.哈希的思想

2.解决冲突

3.哈希表(采用的闭散列,线性探测)

4.哈希桶(开散列)

5.总结


1.哈希的思想

hash是hash是一种根据存储的关键字的哈希值确定存储位置的算法。哈希值通过哈希函数可以计算得出结果,最常用的哈希函数就是除留余数法了。


2.解决冲突

如果俩个关键字值不同但是哈希值相同就会发生不明确存哪的问题,这种情况被称为哈希冲突。

解决冲突的方式1:闭散列,采用用线性探测,即跳过被占用的按顺序向下探测位置。

解决冲突的方式2:开散列,由于是链式结构,所以直接在对应位置串起来即可。


3.哈希表(采用的闭散列,线性探测

上菜:

enum state{empty, //表示空状态exist, //表示占据状态dlete //表示删除状态};template<class K>class HashFunc //仿函数,用来计算关键字的hash值{int operator()(const K& key){return key;}};template<> //特化,采用string的assic码来计算class HashFunc<string>{int operator()(const string& key){int val = 0;for (auto e : key){val *= 131; //结论,用数学公式证明的,用就完了。val += e;}return val;}};template<class K,class V>struct hashnode{state st=empty;pair<K, V> _kv;};template<class K,class V,class Hash=HashFunc<K>>class hashtable{private:vector<hashnode<K,V>> _table;int size = 0;public:bool insert(const pair<K, V>& kv) //插入{if (_table.size() == 0 || 10*size/_table.size() >= 7) //负载因子确定为0.7{int newsize = _table.size() == 0 ? 10 : _table.size() = _table.size() * 2;hashtable<K,V,Hash> newtable; //建立新表newtable._table.resize(newsize); //修改长度for (auto e : _table){//将旧表元素插入到新表中if (e.st == empty){newtable.insert(e._kv);}}_table.swap(newtable._table);//新旧表交换}Hash hash;int val=hash(kv.first); //计算下标int hashi = val % (_table.size()); while (_table[hashi].st == exist) //已经被占据了就继续查找{hashi++;hashi %= (_table.size()); //防止越界}_table[hashi]._kv = kv;_table[hashi].st = exist; //记得标记为占有状态size++; return true;}hashnode<K, V>* find(const K& key) //要找一个循环,因为元素可能发生了冲突{Hash hash;int start = hash(key) % (_table.size()); //标记起始位置int hashi = start;while (hashi != start && _table[hashi].st != empty)//不能为空位置{if (_table[hashi].st != delete && _table[hashi]._kv.first == key){return &_table[hashi];}hashi++;hashi %= (_table.size());}return nullptr;}bool erase(const K& key){hashnode<K, V>* ret = find(key); //复用find查找位置if (ret){ret->st = dlete;--size; //记得--sizereturn true;}return false;}void print() //打印看看结果{for (size_t i = 0; i < _tables.size(); ++i){if (_tables[i].st == exist){printf("[%d:%d] ", i, _tables[i]._kv.first);}else{printf("[%d:*] ", i);}}cout << endl;}};

思路非常简单,先用hash函数找到对应位置。被占住了就继续向后找空位置。写这段代码需要注意的是在扩容时,由于长度的变化,需要映射新的位置。可以采用复用insert的方式完成映射。


4.哈希桶(开散列)

上菜:

#pragma once
#include<iostream>
#include<vector>
using namespace std;template<class K>
struct HashFunc
{int operator()(const K& key){return key;}
};
template<>
struct HashFunc<string>
{int operator()(const string& key){int val = 0;for (auto e : key){val *= 131;val += e;}return val;}
};template<class K, class V>
struct HashNode //链式结构要创建结点
{pair<K, V> _kv;HashNode* _next;HashNode(pair<K, V> kv):_kv(kv), _next(nullptr){}
};template<class K,class V,class Hash=HashFunc<K>>
class Hashtable
{
private:vector<HashNode<K,V>*> _table;int size=0;
public:~Hashtable(){for (int i = 0; i < _table.size(); i++){HashNode<K, V>* cur = _table[i];while (cur){HashNode<K, V>* next = cur->_next; //记录下一个位置delete cur;cur = next;}_table[i] = nullptr; //记得置空}}HashNode<K,V>* find(const K& key){Hash hash;if (_table.size() == 0){return nullptr;}int hashi = hash(key) % _table.size(); //计算位置HashNode<K,V>* cur = _table[hashi];while (cur){if (cur->_kv.first == key) //找到{return cur;}cur = cur->_next;}return nullptr;}bool insert(const pair<K, V>& kv){if (find(kv.first)) //去重return false;if (_table.size() == size || _table.size() == 0) //扩容{int newsize = (_table.size() == 0 ? 10 : _table.size() * 2);Hashtable<K, V, Hash> newtable; //构建新表newtable._table.resize(newsize); for (int i = 0; i < _table.size(); i++){//不能浪费空间,要将原来的资源直接插入到新表就不可以复用。HashNode<K, V>* cur = _table[i];while (cur){HashNode<K, V>* next = cur->_next;Hash hash;int hashi = hash(cur->_kv.first)%(newtable._table.size());cur->_next = newtable._table[hashi];newtable._table[hashi] = cur;cur = next;}}_table.swap(newtable._table);}Hash hash;int hashi = hash(kv.first)%_table.size();HashNode<K, V>* newnode = new HashNode<K, V>(kv);//头插newnode->_next = _table[hashi];_table[hashi] = newnode;++size; //记得++size}
};

同样是先用hash函数找到对应位置,不同的是,可以直接头插不需要移位。唯一需要注意的依然是扩容,这里不可以复用代码,因为旧表的空间必须利用上,不然会出现资源泄露的问题。


5.总结

hash(链式)相对于平衡搜索数(avl 红黑树)有优有劣。

优点:a.对于查找来说,平衡搜索树时间复杂度是O(logn)。而hash的时间复杂度趋近O(1)。

           b.对于插入来说,平衡搜索树需要不断的翻转。而hash直接头插即可。

缺点:a.由于搜索树的性质决定了搜索树可以将数据有序化,而hash是无序的。

           b.随着数据的增大,hash空间消耗会大于平衡搜索树。

hash:哈希表 哈希桶相关推荐

  1. 数据结构与算法五:哈希表-哈希函数设计原则-哈希冲突解决方案

    一.哈希表的定义: 二.哈希表举例: 哈希函数就是映射关系 三.哈希表应用举例: Leetcode上第387题: 思路:通过s.charAt(i)-'a'将字符串中的字符映射成hash表,出现一次,在 ...

  2. 哈希表 哈希函数 时间_您需要了解的哈希函数

    哈希表 哈希函数 时间 安全从业人员的功能表中有一个工具可以帮助每个人理解,无论他们对计算机进行什么操作:加密哈希函数. 这听起来听起来像是神秘的,技术性的,甚至可能很无聊,但是我对什么是哈希以及它们 ...

  3. 哈希表+哈希桶简介及实现

    最近在学习通信协议,链路层传输时,对于报文的识别处理,建立哈希识别规则:之前简单学习过哈希,还没深入过,闲来无事把学习的内容通俗的表达出来,也和大家分享一下,让新入门的童鞋很快理解. 1.哈希表 我们 ...

  4. 哈希表哈希碰撞解决办法

    哈希表: 散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构. 给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若能得到包含 ...

  5. 初识哈希表——哈希表是个啥?

    是什么? 哈希表是一种根据输入信息在已有数据库中快速查找匹配对于信息的算法. 为什么需要? 具体应用场景是,比如在图书管理系统中,用户输入一个图书名称,程序需要在整个图书数据库中找到对应的书籍.如果这 ...

  6. Leetcode 146. LRU缓存机制【哈希表 [哈希表存储每个元素在双向链表中的指针]+双向链表】

    文章目录 问题描述 解题报告 实验代码 参考资料 问题描述 运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制.它应该支持以下操作: 获取数据 get 和 写入数据 put . ...

  7. 【初阶与进阶C++详解】第十九篇:哈希(哈希函数+哈希冲突+哈希表+哈希桶)

  8. 14 哈希表和哈希桶

    文章目录 一.哈希表 二.哈希函数 2.1. 直接定址法(常用) 2.2. 除留余数法(常用) 2.3. 几种不常用的方法 三.哈希冲突 四.闭散列 4.1. 线性探测 4.2. 负载因子 4.3. ...

  9. 哈希表(概念,冲突的解决,实现哈希桶)

    目录 概念 冲突 如何尽量减少冲突? 负载因子 解决冲突的几种方案 冲突严重时的解决办法 哈希表的实现 基本类型哈希桶实现 泛型哈希桶实现 注意!!! 概念 构造出一种存储结构,通过某种函数使元素的存 ...

最新文章

  1. Luogu1714 切蛋糕
  2. php开发神器 -- phpStudy
  3. 第二代计算机网络主要贡献,2010级计算机网络试题
  4. python测网络连通性_网络工程师如何在ensp模拟器上玩python自动化配置交换机。...
  5. amp mysql升级_【简单的案例分享,停机10分钟】10204升级CRSamp;amp;DB的PSU至1
  6. Elasticsearch Java Low Level REST Client(读取响应)
  7. 像素,色彩,分辨率什么的
  8. 软件项目管理:使用PERT评价不确定性的方法
  9. opencv 特征提取 -SIFT
  10. 网课搜题公众号接口怎么对接?最新接口-麦麦题
  11. 在线支付功能的设计及其实现
  12. matlab 压缩感知矩阵_【精读】基于MATLAB的钢筋下料优化算法
  13. 1小时赚300块,不打代码帮人做个吃鸡网页 [IVX实战第3篇]
  14. poj 1745 divisible
  15. Django中多对多查询方式
  16. 23电工杯数学建模A题
  17. Django实现用户管理
  18. python中列表的操作
  19. 【路径规划】基于蚁群算法求解公交车路径规划问题matlab源码
  20. 制作64M启动型+系统维护U盘,支持WINPE+CDLinux+DOS7

热门文章

  1. android widget 点击事件,Android Widget点击事件
  2. 牛客-牛客练习赛24-B 凤 凰
  3. 芋道项目搭建注意事项
  4. raise ContentTooShortError(urllib.error.ContentTooShortError: <urlopen error retrieval incomplete:
  5. 考研数学:秩为1的矩阵的特征值分析
  6. 3016 质子撞击炮 II
  7. hydra的基本使用
  8. win7怎么设置计算机的性能,windows7旗舰版电脑如何为电脑设置高性能计划
  9. Skywalking光会用可不行,必须的源码分析分析 - Skywalking Agent 插件解析
  10. 家里 无线 硬盘 服务器,无线路由器 硬盘组云服务器