由于STL没有提供hashmap (map、set其实是一个有序平衡树),在性能敏感时,Linux C++下一般使用ACE Hash_Map库来做哈希表。找了半天没找到中文文档,自己写一篇吧。
其官方文档在:http://www.dre.vanderbilt.edu/Doxygen/6.0.6/html/libace-doc/a00263.html
简单说,其步骤包括:
1) 声明
说明你的Key类型、Value类型、Key的哈希方法(用一个回调函数对象)、Key的比较方法、是否加锁
对于大多数简单类型(字符串除外)这并不难,因为这些类型已经有ACE库支持,如初始化<int,float>哈希表:
#include "ace/Hash_Map_Manager.h"
#include "ace/Malloc_T.h"
#include "ace/Null_Mutex.h"
ACE_Hash_Map_Manager_Ex<int, float, ACE_Hash<int>, ACE_Equal_To<int>, ACE_Null_Mutex> myhashtable;
2)初始化分配内存
if(myhashtable.open(500000) != 0)
fprintf(stderr,"ERROR: can not set hashmap, check if memory has met limit!");
3)填充数值
myhashtable.bind(123, 1.23); //建立 <123 -> 1.23> 哈希表
//(重复的key bind时只有第一次生效,若不符合需求请用trybind()等其它函数)
4)查找哈希表
int key = 123; // set the key you want find
float value = 0.0; // the value will be stored here if key is found
status = myhashtable.find(key, value);
if( 0 == status) { printf("%f", value); } // the key is found
else {} // the key do not exist
==============================================
字符串做key时,ACE没有提供直接支持,要用ACE_CString。
===============================================
这里注意1:不能用ACE_Hash<char*>,否则很容易死的时候都不知道怎么死的... 这里只保存指针地址没有字符串内容,再加上编译器飘柔的优化态度,各种奇葩结果彻底击溃你的逻辑。
这里注意2:不能用ACE_Hash<std::string>,虽然ACE愿意,但是std::string不支持,编不过的。
目前的网上资料(其实是一份被拷来拷去)会建议你自己定义一个ACE_Hash<string>,还return 1000...。且不说这个1000多么⊙﹏⊙b汗,起码这个方法很不方便。解决方案其实很简单,只需知道ACE_CString以及ACE_CString与char*的转换:
英文技术文档:http://www.theaceorb.com/1.2a/doxygen/ace/classACE__CString.html
最关键的3个函数:
ACE_CString (const char *s, ACE_Allocator *alloc=0, int release=1)
void set (const char *s, int release=1) //Copy <s> into this <ACE_CString>. Memory is _not_ allocated/freed if <release> is 0.
const char * c_str (void) const //Same as STL String's <c_str> and <fast_rep>.
示例:
#include "ace/Hash_Map_Manager.h"
#include "ace/Malloc_T.h"
#include "ace/Null_Mutex.h"
ACE_Hash_Map_Manager_Ex<ACE_CString, float, ACE_Hash<ACE_CString>, ACE_Equal_To<ACE_CString>, ACE_Null_Mutex> hash;
ACE_CString ace = str2ace("I'm a c str or char array, end with 0");
float value=8.8;
hash.bind(ace, value);
float tmp = 0.0;
int status = hash.find(ace, tmp);
fprintf(stderr, "find [str=%s] [status=%d], [value=%.3f]", ace.c_str(), status, tmp);