哈希表的优点
1. 速度快:不论表中有多少数据,插入删除和查找都只需要接近常量的时间0(1)(wikipedia原文:
Hash tables support the efficient lookup, insertion and deletion of elements in constant time on average (O(1)) that does not vary with the number of elements stored in the table;)
2. 编程实现相对容易(相对树std::map而言)。
哈希表的缺点
1. 基于数组:数组创建后难于扩展;某些哈希表被基本填满时,性能下降得非常严重,所以程序虽必须要清楚表中将要存储多少数据(或者准备好定期地把数据转移到更大的哈希表中,这是个费时的过程)。
2. 难于遍历:没有一种简便的方法可以以任何一种顺序〔例如从小到大〕遍历表中数据项。如果需要这种能力,就只能选择其他数据结构。
何时选择哈希表
1. 如果不需要有序遍历数据,并且可以提前预测数据量的大小,那么哈希表在速度和易用性方面是无与伦比的。
2. 如果需要在一秒种内查找上千条记录通常使用哈希表(例如拼写检查器或者数据库);哈希表的速度明显比树快,树的操作通常需要O(N)的时间级。
哈希表基本原理
1. 准备大数组用以存储用户数据,数组索引称之为哈希键(hash key)
2. 通过将用户键(user key)转换为哈希键(hash key),并在数组中找寻哈希键对应之数据(bucket)。
3. 通常hash键做取模操作以转换为正确范围之数组索引
哈希键冲突
理论上通过某种方法(哈希函数hash function)可以使得用户键与哈希键一一对应,但实际上很难找到这样的哈希算法(只能接近,wikipedia原文:A nonzero collision probability is inevitable in any hash implementation)。
如果某种哈希算法使得两个用户键对应同一个哈希键,这种状况被称之为键冲突(wikipedia原文:in some cases, the calculated index can be the same for two different keys (a "collision"))
如何解决冲突
1. 开放定址法
2. 再哈希法:当发生冲突时,使用第二个、第三个、哈希函数计算地址,直到无冲突时。缺点:计算时间增加。
3. 链地址法:将所有关键字为同义词的记录存储在同一线性链表中;

哈希表设计难点
1. 哈希表的大小多少合适?
2. 如何选择哈希算法尽可能减小冲突
3. 冲突时采用哪种解决方案
对于1,太大了可能浪费,太小了速度就慢;可以参考这篇文章http://www.wangchao.net.cn/bbsdetail_27962.html
对于3,冲突解决方案常用的有开放定址法(Open addressing)和链地址法(Separate chaining):
(wikipedia原文:There are a number of collision resolution techniques, but the most popular are open addressing and chaining.)
链地址法比较常用,实作也简单;这也是为什么通常称哈希表为哈希链表的原因。(wikipedia原文:链地址vs开放地址的优缺点)
对于2,主要从算法引起冲突的次数要尽可能少和算法本身要快着手;可参考
经典的Hash算法的实现(源代码)
选择好的Hash函数