哈希表 学习
看了几篇文章,主要意思就是用简单的值index,去索引复杂的值key,进而找到想要的值value.
哈希算法主旨:index = f(key)
数据存放格式:(key.value)
但是存在问题是,
1.哈希算法使不同的key产生相同的index
2.分配给哈希表的内存满了之后,整个哈希表的迁移太累赘了。
针对第一个问题,下面介绍两个方案:
拉链法:http://www.cnblogs.com/xiekeli/archive/2012/01/13/2321207.html
相同index的键值对,就用链表往后去存储。
typedef struct _node{ char *key; char *value; struct _node *next; }node; #define HASHSIZE 101 static node* hashtab[HASHSIZE]; //hash index
哈希桶:http://www.cnblogs.com/xiekeli/archive/2012/01/16/2323391.html
struct Pair { char *key; char *value; }; struct Bucket { unsigned int count; Pair *pairs; }; struct StrMap { unsigned int count; Bucket *buckets; };
首先哈希桶的个数是固定的,有用户构建的时候输入,一旦构建,个数就已经固定;查找的时候首先将key值通过哈希函数获取哈希值,根据哈希值获取到对应的哈希桶,然后遍历哈希桶内的pairs数组获取;
这两种实现方法看似比较类似,但也有差异:
基于哈希桶的情况下,由于Hash桶容量的限制,所以,有可能发生Hash表填不满的情况,也就是,虽然Hash表里面还有空位,但是新建的表项由于冲突过多,而不能装入Hash表中。不过,这样的实现也有其好处,就是查表的最大开销是可以确定的,因为最多处理的冲突数是确定的,所以算法的时间复杂度为O(1)+O(m),其中m为Hash桶容量。
而另一种通过链表的实现,由于Hash桶的容量是无限的,因此,只要没有超出Hash表的最大容量,就能够容纳新建的表项。但是,一旦发生了Hash冲突严重的情况,就会造成Hash桶的链表过长,大大降低查找效率。在最坏的情况下,时间复杂度退化为O(n),其中n为Hash表的总容量。当然,这种情况的概率小之又小,几乎是可以忽略的。
比较好的代码:
http://blog.csdn.net/smstong/article/details/51145786
。