算法:哈希表格(Hash Table)
背景
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)的更多相关文章
- 算法与数据结构基础 - 哈希表(Hash Table)
Hash Table基础 哈希表(Hash Table)是常用的数据结构,其运用哈希函数(hash function)实现映射,内部使用开放定址.拉链法等方式解决哈希冲突,使得读写时间复杂度平均为O( ...
- PHP关联数组和哈希表(hash table) 未指定
PHP有数据的一个非常重要的一类,就是关联数组.又称为哈希表(hash table),是一种很好用的数据结构. 在程序中.我们可能会遇到须要消重的问题,举一个最简单的模型: 有一份username列表 ...
- 算法导论-散列表(Hash Table)-大量数据快速查找算法
目录 引言 直接寻址 散列寻址 散列函数 除法散列 乘法散列 全域散列 完全散列 碰撞处理方法 链表法 开放寻址法 线性探查 二次探查 双重散列 随机散列 再散列问题 完整源码(C++) 参考资料 内 ...
- 词典(二) 哈希表(Hash table)
散列表(hashtable)是一种高效的词典结构,可以在期望的常数时间内实现对词典的所有接口的操作.散列完全摒弃了关键码有序的条件,所以可以突破CBA式算法的复杂度界限. 散列表 逻辑上,有一系列可以 ...
- 什么叫哈希表(Hash Table)
散列表(也叫哈希表),是根据关键码值直接进行访问的数据结构,也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度.这个映射函数叫做散列函数,存放记录的数组叫做散列表. - 数据结构 ...
- 数据结构 哈希表(Hash Table)_哈希概述
哈希表支持一种最有效的检索方法:散列. 从根来上说,一个哈希表包含一个数组,通过特殊的索引值(键)来访问数组中的元素. 哈希表的主要思想是通过一个哈希函数,在所有可能的键与槽位之间建立一张映射表.哈希 ...
- 白话算法(6) 散列表(Hash Table)从理论到实用(上)
处理实际问题的一般数学方法是,首先提炼出问题的本质元素,然后把它看作一个比现实无限宽广的可能性系统,这个系统中的实质关系可以通过一般化的推理来论证理解,并可归纳成一般公式,而这个一般公式适用于任何特殊 ...
- 白话算法(6) 散列表(Hash Table) 从理论到实用(下)
[澈丹,我想要个钻戒.][小北,等等吧,等我再修行两年,你把我烧了,舍利子比钻戒值钱.] ——自扯自蛋 无论开发一个程序还是谈一场恋爱,都差不多要经历这么4个阶段: 1)从零开始.没有束缚的轻松感.似 ...
- 白话算法(6) 散列表(Hash Table)从理论到实用(中)
不用链接法,还有别的方法能处理碰撞吗?扪心自问,我不敢问这个问题.链接法如此的自然.直接,以至于我不敢相信还有别的(甚至是更好的)方法.推动科技进步的人,永远是那些敢于问出比外行更天真.更外行的问题, ...
- 哈希表(Hash table)
随机推荐
- C# 图片和二进制之间的转换
1> 图片转二进制 public byte[] GetPictureData(string imagepath){/**/////根据图片文件的路径使用文件流打开,并保存为byte[] Fil ...
- Linux下的堆伪造漏洞利用技术(new unlink)
感觉markdown的文件格式看起来更清晰一些就写成附加的形式了.Download 更正:这种利用方式不叫House of Mind,是我搞混了.
- 聊一聊FE面试那些事【原创】
最近公司由于业务的扩展.技术的延伸需要招一批有能力的小伙伴加入,而我有幸担任"技术面试官"的角色前前后后面试了不下50多位候选人,如同见证了50多位前端开发者的经历一样,在面试的过 ...
- drools7 (二、agenda-group 的使用)
几个关键点: 1. 如果没有指定agenda-group 则默认把所有未指定agenda-group的 rules 都执行一遍 2. 如果指定了agenda-group 使用的时候必须指定该name才 ...
- inotify 与 rsync文件同步实现与问题
首先分别介绍inotify 与 rsync的使用,然后用两者实现实时文件同步,最后说一下这样的系统存在什么样的问题. 1. inotify 这个具体使用网上很多,参考 inotify-tools 命令 ...
- 【转】TCP建立连接三次握手和释放连接四次握手
在谈及TCP建立连接和释放连接过程,先来简单认识一下TCP报文段首部格式的的几个名词(这里只是简单说明,具体请查看相关教程) 序列号seq:占4个字节,用来标记数据段的顺序,TCP把连接中发送的所有数 ...
- WCF服务发布到IIS中去(VS2013+win7系统)
第一个WCF程序 1. 新建立空白解决方案,并在解决方案中新建项目,项目类型为:WCF服务应用程序.建立完成后如下图所示: 2.删除系统生成的两个文件IService1.cs与Service1.svc ...
- Scala入门1(单例对象和伴生类)
一.Hello World程序的执行原理 参考http://blog.csdn.net/zhangjg_blog/article/details/22760957 object HelloWorld{ ...
- JAVA单向链表实现
JAVA单向链表实现 单向链表 链表和数组一样是一种最常用的线性数据结构,两者各有优缺点.数组我们知道是在内存上的一块连续的空间构成,所以其元素访问可以通过下标进行,随机访问速度很快,但数组也有其缺点 ...
- POJ 3254 & POJ 1185(状压DP入门)
Corn Fields Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 16773 Accepted: 8860 Desc ...