引言问题

作为资深老鸟,有事没事,出去面试;找准差距、定位价值。

面试必谈哈希,

Q1:什么是哈希?

Q2:哈希为什么快?

Q3:你是怎么理解哈希算法利用空间换取时间的?

Q4:你是怎么解决哈希冲突的?

Q5:你有实际用写过哈希算法吗?

知识储备

  哈希(也叫散列)是一种查找算法(可用于插入),哈希算法希望能做到不经过任何比较(发生冲突,还是需要少许比较),通过一次存取就能得到查找的数据。

因此哈希的关键在key和数据元素的存储位置之间建立一个确定的对应关系,每个key在哈希表中都有唯一的地址相对应(形成有限、连续的地址空间),查找时根据对应关系经过一步计算得到key在散列表的位置。

在数学上, 原Key叫做原像,由映射函数h(key)映射的存储位置叫做像;在IT领域,以上存储位置叫哈希地址(散列地址),这个映射过程叫做哈希/散列。

故我们可以预见:

  ① 不同的key值,由哈希函数h(x) 作用后可能映射到同一个哈希地址, 这就是哈希冲突,冲突发生的概率取决于 定义的哈希函数

  ② 由哈希表作用后的哈希地址需要空间存储,这一系列连续相邻的地址空间叫哈希表、 散列表。

处理哈希冲突可分为两大类:

  (1)开散列法发生冲突的元素存储于数组空间之外。可以把“开”字理解为需要另外“开辟”空间存储发生冲突的元素, 又称【链地址法】

  (2)闭散列法发生冲突的元素存储于数组空间之内。可以把“闭”字理解为所有元素,不管是否有冲突,都“关闭”于数组之中,闭散列法又称【开放定址法】,意指数组空间对所有元素,不管是否冲突都是开放的

   哈希表是用数组实现的一片连续的地址空间,两种冲突解决方案的区别在于发生冲突的元素是存储在这片数组的空间之外还是空间之内

2. 看图说话

----------------------------以下是开散列法(链地址法)解决冲突的示意图---------------------------
 

  从图上看实现【哈希】过程分两部分:

① 哈希函数

  收敛函数,不可避免会冲突,需要思考设定一个均衡的哈希函数,使哈希地址尽可能均匀地分布在哈希地址空间

②  构造哈希表 + 冲突链表

  装填因子loadfactor :所谓装填因子是指哈希表中已存入的记录数n与哈希地址空间大小m的比值,即 α=n / m ,α越小,冲突发生的可能性就越小;α越大(最大可取1),冲突发生的可能性就越大;另一方面,α越小,存储窨的利用率就越低;反之,存储窨的利用率就越高。

为了既兼顾减少冲突的发生,又兼顾提高存储空间的利用率,通常把α控制在0.6~0.9的范围之内

哈希在.Net中的应用

GetHashCode方法

  Object基类中有GetHashCode方法,HashCode是一个数字值,用于在【基于哈希特性的集合】中插入和查找某对象;GetHashCode方法为需要快速检查对象相等性的算法提供此哈希代码;

  Do not test for equality of hash codes to determine whether two objects are equal. (Unequal objects can have identical hash codes.) To test for equality, call the ReferenceEquals or Equals method.  (重要的话要读3遍)

单纯判断【逻辑相等】时,本无所谓重写 GetHashCode方法;但若在基于hash的集合中快速查找/插入某元素,则一定要重写GetHashCode方法。

最新文章

  1. Windows中explorer(图形壳)
  2. Redis服务器的启动过程分析
  3. WebSocket 学习笔记--IE,IOS,Android等设备的兼容性问题与代码实现
  4. 5.2 i++
  5. js怎样改变div的宽度
  6. iOS 各种控件默认高度
  7. YouTube CEO关于工作和生活平衡的完美回答
  8. iOS 用RunTime来提升按钮的体验
  9. 最简单的基于FFmpeg的视频编码器-更新版(YUV编码为HEVC(H.265))
  10. 用boost::bind构造boost::coroutine
  11. 转://从一条巨慢SQL看基于Oracle的SQL优化
  12. 初识 go 语言:数据类型
  13. json 模块 与 pickle 模块
  14. 安装mysql后在/var/log/mysqld.log 中找不到临时密码
  15. 17.0-uC/OS-III消息管理
  16. Eclipse导入jdk的源码
  17. [转]使用CMS垃圾收集器产生的问题和解决方案
  18. ORACLE SEQUENCE 具体解释
  19. Myeclipse2016安装Aptana
  20. C回调函数

热门文章

  1. 最全java多线程总结3——了解阻塞队列和线程安全集合不
  2. Fastjson的SerializerFeature序列化属性
  3. 设计模式之策略模式和状态模式(strategy pattern & state pattern)
  4. GitLab安装后修改IP/域名
  5. C++ luogu1352没有上司的舞会 from_树形DP
  6. 并发编程-concurrent指南-原子操作类-AtomicReference
  7. .Net 通过设置Access-Control-Allow-Origin来实现跨域访问
  8. Java第四次作业——面向对象高级特性(继承和多态)
  9. Jenkins高级应用——Publish Over SSH插件
  10. Jenkins构建部署jar/war后,服务无法在后台持续运行的解决方案