最近一直搞字符串的哈希查找,有人推荐使用gperf的Perfect Hash,于是去调查了一下GPerf的使用方法。
gperf 下载 http://www.gnu.org/software/gperf/,ubuntu上可以直接sudo apt-get install gperf ,可能办法不是最新的。
gperf 文档 http://www.gnu.org/software/gperf/manual/gperf.html#Functions
我主要参考了《使用 gperf 实现高效的 C/C++ 命令行处理》。
gperf使用:
主要是declarations和keyword部分,如果只是单纯的查找字符串是否存在,则不需要declarations部分,.gperf文件中直接保存哈希表中的所有字符串即可。但是哈希表中一般都是key和value对,这样的要在declaration部分声明一个struct,然后两个%%后是keyword。格式如下:
struct KeyValue { const char * key;//第一个字段必须是const char * int value; //可以有更多的value值 }; %% key1,1 key2,2 key3,3
keyword部分如果首字符为%,该字符串须用双引号括起来,如%key,必须是“%key”。
然后使用gperf命令生成hpp文件:
gperf -CGD -K key -L C++ -t xxx.gperf > perfecthash.hpp
生成的头文件中有Perfect_Hash的类,类名可以通过-Z选项修改。
类中有Hash函数,默认为hash(),可以通-H选项修改。
查找函数是in_word_set(),用-N来修改。
-L指定编程语言。
如果有declaration部分,必须使用-t选项。
-K指定struct中关键字的名称。
具体的原理不做详细说明,Perfect Hash应该很快,没有实际测试过。
问题:
gperf只是把.gperf文件中的关键字使用结构体数组的形式存放在代码文件中,省去了文件加载的时间,然而感觉这种做法只适合小规模的hash查找,如参考中的C++命令行处理。对于我要处理的几十万或者上百万的字符串索引对,并不适合使用gperf来处理。
不知道是否有人处理过大规模的字符串Hash查找,是否有更好的解决方案,望请赐教,谢谢。