哈希表(Hash table,也叫散列表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
散列表是算法在时间和空间上作出权衡的经典例子
如果没有内存限制,我们可以直接将键作为(可能是一个超大的)数组的索引,那么所有查找操作只需要访问内存一次即可完成。但这种理想情况不会经常出现,因为当键很多时需要的内存太大。另一方面,如果没有时间限制,我们可以使用无序数组并进行顺序查找,这样就只需要很少的内存。而散列表则使用了适度的空间和时间并在这两个极端之间找到了一种平衡。事实上,我们不必重写代码,只需要调整散列算法的参数就可以在空间和时间之间作出取舍。我们会使用概率论的经典结论来帮组我们选择适当的参数。
使用Hash的查询算法分为两步:
① 用Hash函数将被查找的键转化为数组的一个索引。
理想情况下,不同的键都能转化为不同的索引值。当然,这只是理想情况,所以我们需要面对两个或者多个键都会散列到相同的索引值的情况。
② 处理碰撞冲突的过程
下面是个小例子:
using System;
using System.Collections;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Hashtable ht = new Hashtable();
ht.Add("animation1", "天行九歌");
ht.Add("animation2", "万剑仙踪");
ht.Add("animation3", "灵笼");
ht.Add("animation4", "斗破苍穹");
ht.Add("animation5", "斗罗大陆");
ht.Add("animation6", "灵主");
ht.Add("animation7", "不良人");
if (ht.ContainsValue("换世门生"))
{
Console.WriteLine("This animation name is already in the list");
}
else
{
ht.Add("animation8", "换世门生");
}
// 获取键的集合
ICollection key = ht.Keys;
foreach (string k in key)
{
Console.WriteLine(k + ": " + ht[k]);
}
Console.ReadKey();
}
}
}
运行结果: