背景

Java 和 .Net 平台都有一个所有引用类型都会间接或直接继承的类型:Object,这个类型提供最基本的相等性比较算法和哈希算法,很多书上都给出了在重写这两个算法的时候的主意事项,其中大多数主意事项都和哈希表有关。

《CLR VIA C#》的作者觉得将哈希算法放到 Object 不是很适合,我也有这种感觉,每次重写相等性比较算法都要重新哈希算法,非常不爽,我就没打算将其用到哈希表中作为键使用。

哈希表

定义

使用哈希算法将 A 数值空间(键)映射到 B 数值空间(存储),如下:

A -> 0

B -> 1

C -> 2

D -> 3

B 数值空间的查询速度要求非常快,毫无疑问就是数值了。

冲突

数组的大小是固定,当出现冲突(两个键映射为同一个数值了)的时候如何处理呢?有两种策略:

  • 在数组中按照一定的算法继续探测其它地址。
  • 在数组的每个元素存储的都是链表,冲突的元素会被插入到链表中。

实现

链表节点

         class Node<TKey, TValue>
{
public TKey Key { get; set; } public TValue Value { get; set; } public Node<TKey, TValue> Next { get; set; }
}

链表

         class LinkedList<TKey, TValue>
{
public Node<TKey, TValue> First { get; set; } public void Insert(TKey key, TValue value)
{
if (this.Contains(key))
{
throw new InvalidOperationException("不能插入重复的键");
} var node = new Node<TKey, TValue> { Key = key, Value = value };
node.Next = this.First;
this.First = node;
} public void Delete(TKey key)
{
Node<TKey, TValue> parent;
Node<TKey, TValue> node; if (!this.Find(key, out parent, out node))
{
throw new InvalidOperationException("不存在指定的键");
} if (parent == null)
{
this.First = null;
}
else
{
parent.Next = node.Next;
}
} public bool Contains(TKey key)
{
Node<TKey, TValue> parent;
Node<TKey, TValue> node; return this.Find(key, out parent, out node);
} public bool Find(TKey key, out Node<TKey, TValue> node)
{
Node<TKey, TValue> parent; return this.Find(key, out parent, out node);
} public bool Find(TKey key, out Node<TKey, TValue> parent, out Node<TKey, TValue> node)
{
parent = null;
node = this.First; while (node != null)
{
if (node.Key.Equals(key))
{
return true;
} parent = node;
node = node.Next;
} return false;
}
}

哈希表

         class HashTable<TKey, TValue>
{
private LinkedList<TKey, TValue>[] _items; public HashTable(int size)
{
_items = new LinkedList<TKey, TValue>[size];
} public void Insert(TKey key, TValue value)
{
var index = this.HashToIndex(key);
if (_items[index] == null)
{
_items[index] = new LinkedList<TKey, TValue>();
} _items[index].Insert(key, value);
} public void Delete(TKey key)
{
var index = this.HashToIndex(key);
if (_items[index] == null)
{
throw new InvalidOperationException("不存在指定的键");
} _items[index].Delete(key);
} public bool Find(TKey key, out TValue value)
{
value = default(TValue); var index = this.HashToIndex(key);
if (_items[index] == null)
{
return false;
} Node<TKey, TValue> node;
var finded = _items[index].Find(key, out node);
if (!finded)
{
return false;
}
else
{
value = node.Value;
} return true;
} private int HashToIndex(TKey key)
{
return key.GetHashCode() % _items.Length;
}
}

备注

哈希算法、负载因子、自动扩容都是需要考虑的,这里就不多说了。

算法:哈希表格(Hash Table)的更多相关文章

  1. 算法与数据结构基础 - 哈希表(Hash Table)

    Hash Table基础 哈希表(Hash Table)是常用的数据结构,其运用哈希函数(hash function)实现映射,内部使用开放定址.拉链法等方式解决哈希冲突,使得读写时间复杂度平均为O( ...

  2. PHP关联数组和哈希表(hash table) 未指定

    PHP有数据的一个非常重要的一类,就是关联数组.又称为哈希表(hash table),是一种很好用的数据结构. 在程序中.我们可能会遇到须要消重的问题,举一个最简单的模型: 有一份username列表 ...

  3. 算法导论-散列表(Hash Table)-大量数据快速查找算法

    目录 引言 直接寻址 散列寻址 散列函数 除法散列 乘法散列 全域散列 完全散列 碰撞处理方法 链表法 开放寻址法 线性探查 二次探查 双重散列 随机散列 再散列问题 完整源码(C++) 参考资料 内 ...

  4. 词典(二) 哈希表(Hash table)

    散列表(hashtable)是一种高效的词典结构,可以在期望的常数时间内实现对词典的所有接口的操作.散列完全摒弃了关键码有序的条件,所以可以突破CBA式算法的复杂度界限. 散列表 逻辑上,有一系列可以 ...

  5. 什么叫哈希表(Hash Table)

    散列表(也叫哈希表),是根据关键码值直接进行访问的数据结构,也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度.这个映射函数叫做散列函数,存放记录的数组叫做散列表. - 数据结构 ...

  6. 数据结构 哈希表(Hash Table)_哈希概述

    哈希表支持一种最有效的检索方法:散列. 从根来上说,一个哈希表包含一个数组,通过特殊的索引值(键)来访问数组中的元素. 哈希表的主要思想是通过一个哈希函数,在所有可能的键与槽位之间建立一张映射表.哈希 ...

  7. 白话算法(6) 散列表(Hash Table)从理论到实用(上)

    处理实际问题的一般数学方法是,首先提炼出问题的本质元素,然后把它看作一个比现实无限宽广的可能性系统,这个系统中的实质关系可以通过一般化的推理来论证理解,并可归纳成一般公式,而这个一般公式适用于任何特殊 ...

  8. 白话算法(6) 散列表(Hash Table) 从理论到实用(下)

    [澈丹,我想要个钻戒.][小北,等等吧,等我再修行两年,你把我烧了,舍利子比钻戒值钱.] ——自扯自蛋 无论开发一个程序还是谈一场恋爱,都差不多要经历这么4个阶段: 1)从零开始.没有束缚的轻松感.似 ...

  9. 白话算法(6) 散列表(Hash Table)从理论到实用(中)

    不用链接法,还有别的方法能处理碰撞吗?扪心自问,我不敢问这个问题.链接法如此的自然.直接,以至于我不敢相信还有别的(甚至是更好的)方法.推动科技进步的人,永远是那些敢于问出比外行更天真.更外行的问题, ...

  10. 哈希表(Hash table)

随机推荐

  1. C# 图片和二进制之间的转换

    1> 图片转二进制  public byte[] GetPictureData(string imagepath){/**/////根据图片文件的路径使用文件流打开,并保存为byte[] Fil ...

  2. Linux下的堆伪造漏洞利用技术(new unlink)

    感觉markdown的文件格式看起来更清晰一些就写成附加的形式了.Download 更正:这种利用方式不叫House of Mind,是我搞混了.

  3. 聊一聊FE面试那些事【原创】

    最近公司由于业务的扩展.技术的延伸需要招一批有能力的小伙伴加入,而我有幸担任"技术面试官"的角色前前后后面试了不下50多位候选人,如同见证了50多位前端开发者的经历一样,在面试的过 ...

  4. drools7 (二、agenda-group 的使用)

    几个关键点: 1. 如果没有指定agenda-group 则默认把所有未指定agenda-group的 rules 都执行一遍 2. 如果指定了agenda-group 使用的时候必须指定该name才 ...

  5. inotify 与 rsync文件同步实现与问题

    首先分别介绍inotify 与 rsync的使用,然后用两者实现实时文件同步,最后说一下这样的系统存在什么样的问题. 1. inotify 这个具体使用网上很多,参考 inotify-tools 命令 ...

  6. 【转】TCP建立连接三次握手和释放连接四次握手

    在谈及TCP建立连接和释放连接过程,先来简单认识一下TCP报文段首部格式的的几个名词(这里只是简单说明,具体请查看相关教程) 序列号seq:占4个字节,用来标记数据段的顺序,TCP把连接中发送的所有数 ...

  7. WCF服务发布到IIS中去(VS2013+win7系统)

    第一个WCF程序 1. 新建立空白解决方案,并在解决方案中新建项目,项目类型为:WCF服务应用程序.建立完成后如下图所示: 2.删除系统生成的两个文件IService1.cs与Service1.svc ...

  8. Scala入门1(单例对象和伴生类)

    一.Hello World程序的执行原理 参考http://blog.csdn.net/zhangjg_blog/article/details/22760957 object HelloWorld{ ...

  9. JAVA单向链表实现

    JAVA单向链表实现 单向链表 链表和数组一样是一种最常用的线性数据结构,两者各有优缺点.数组我们知道是在内存上的一块连续的空间构成,所以其元素访问可以通过下标进行,随机访问速度很快,但数组也有其缺点 ...

  10. POJ 3254 & POJ 1185(状压DP入门)

    Corn Fields Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 16773   Accepted: 8860 Desc ...