散列表(HashTable)

HashSet

elem1,elem2,elem3...若是这一系列元素放到数组

  • 数组;查找O(n),插入O(n),删除O(n)
  • 链表;查找o(n),插入o(1),删除o(1)
  • HashSet;查找o(1),插入o(1),删除o(1)

HashSet的实现原理

HashSet是经过数组查找复杂度为0(1)实现的.
数组[hashfunction(elem)] = elem
clipboard.png缓存

彻底一致散列

每一个key生成的数组索引都是惟一的,且全部key生成的数组索引互不相同.服务器

非彻底一致散列

每一个key生成的数组索引都是惟一的,可是存在多个key生成的数组索是相同的状况.
这时,就有了冲突,填充因子,重构哈希表等概念了.数据结构

[针对彻底一致散列的散列表的查找,插入,删除过程]
利用元素进行哈希函数运算获得数组的索引,而后把该元素放置到数组的索引单元中.
查找时,进行哈希计算迅速获得元素的位置,若是该位置是null,代表无此元素;
插入时,通过哈希运算,找到存储位置,检查存储位置若是为null,则插入;若是不是null,代表已经存在,则出错;因此将元素插入时,建议插入前先检查是否已经存在待插入的元素.
删除时同理,置为null便可.函数

散列表

散列表,又称字典,关联数组。
一系列key-value形式的元素存放到某种数据结构中,能经过key迅速找到该数据对,如
电话薄中的手机号码,[姓名,号码]
(张三,18700977521)
(李四,15810387653)
(王二,13190008765)性能

实现方案

咱们先根据key生成key的hashset(数组a),而后额外建立一个数组b,数组b和数组a长度相同;假设key1在数组a中的索引是h(key1),那么咱们就在数组b的h(key1)索引单元放置key1对应的value1.
当咱们查找某个key的value时,经过h(key)获得其value在数组b中的索引.
当咱们判断散列表是否已经包含key-value对时,取得key的hashset数组a,便可0(1)时间内实现判断.
切记,数组a和数组b称为关联数组,数组a是hashset,可是存放value的数组b并非hashset,它只是哥普通数组.spa

clipboard.png

散列表的应用案例

  1. 手机的联系人列表,能快速定位到某个朋友的手机号码.
  2. 去重.将一堆元素逐个扔进散列表,重复的就丢弃,时间复杂度是o(n)
  3. 缓存.某一Twitter用户对服务器发出请求,服务器计算获得相应的界面,发送给用户;对于登录,注册等界面,全部的用户都是相同的,咱们能够把这些固定不变的界面缓存下来,放入到一个字典中.

clipboard.png
4.dns解析.key是域名,value是ip索引

HashTable的瓶颈

碰撞

多个key通过哈希函数的计算获得的数组索引值相同,称为碰撞.
解决碰撞的办法有:(1)连接法 (2)开放地址法dns

装载因子

装载因子 = 散列表的元素数目 / 数组长度
当装载因子 达到0.7时,建议延长散列表的长度,不至于使数组每一个单元连接的元素数目太长,下降了散列表的性能.ip

证实哈希表的时间复杂度是O(1)

假设n个元素,数组长度是m,哈希函数具备良好的随机性,那么咱们查找某个元素的时间复杂度是O(n/m),同时咱们会在填充因子大于0.7时扩充数组的长度,即,n和m是线性关系,m = kn(k是常数),因此有 O(n/m) = O(n / kn) = O(1/k) = O(1).

HashTable的最坏状况

HashTable容许出现碰撞,可是若是采用的哈希函数极其恶心,把不少key都连接到数组的相同索引,这时候查找的时间复杂度是O(n).一个好的哈希函数是HashTable的命,直接决定散列表的性能.一个好的哈希函数应该让每一个key独立且随机的生成索引,从而尽量的逼近这样的一种状态:数组的绝大部分单元都连接了元素,且每一个单元连接的元素数目大体相等.最佳状态称为彻底一致散列,即数组的每一个单元都存放一个元素!

相关文章
相关标签/搜索