您的位置:首页 > 其它

通过建立hash表快速搜索资源

2012-08-11 12:37 169 查看
Hash,一般翻译做“散列”,也有直接音译为“哈希”的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数.

在做某游戏资源管理时采用了建立hash表来快速索引寻获目标纹理的地址,因为采用了<key,val>(<string,struct>)的结构来标识一个目标,所以想到将key直接转化为地址,到网上搜索了下,最为经典的字符串hash算法是ELFhash(hash的百科中有介绍)

inline unsigned int ELF_hash(wchar_t *name)
{
unsigned long h = 0, g;
while(*name)
{
h = (h << 4) + *name++;
if(g = h & 0xf0000000)
h ^= g >> 24;
h &= ~g;
}
return (h%65536);
}

建立一个256x256大小的hash表

texlist *texlist_headp[256*256];
这里的每一个元素是一个链表头指针,为什么使用链表呢,不直接将tex对象存入hash表中呢? 要知道hash算法是一种散列算法,不管算法的效率再怎么高也会产生冲突,也就是发生有两个key经过hash后值是一样的,那这两个val都会存到同一个表项中,所以需要建立一个链表,将<key,value>再push入链表,  要注意的是经过hash分布后的这些链表遍历的效率将会十分高,因为有两个特点决定了这个优势.
一是因为hash散列的效果,注定很少情况下会产生冲突(当然,产生冲突的概率依算法的效率而定),那么每个链表的元素将会十分少,遍历时间必然会大幅度减少;

二是因为hash的特点,产生冲突的key的差异必将非常大(例如: "abcd" 和 "这是一个key" ),key在长度和特征上必将具有很大差异,在遍历时的筛选速度会大为提高(例如本例的用string作为key,通常strcmp只需判断前两个字符就可以筛掉不是目标的项,如果还要更快的速度的话,可以len特征,例如<key,keylen,value>,遍历链表时先对比keylen的大小,如果相同再strcmp),这在某些领域上优势是十分巨大的.

例如有以下命名习惯的key组:

地图_草原
地图_森林
人物_路人1
人物_路人2
模型_a
模型_b
具有大量相同特征(前置相同)的key,无法想象直接将这些所有key放在同一个链表中遍历的速率,那将会是一个前所未有的低效寻址效率.所以通过建立hash表是一个十分有效的解决资源储存&取出的方法,当然一切的前提是你具有比较多的数据,只有两三个资源不言而喻链表和hash表没什么效率可评论,^_^
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法 string struct 游戏