您的位置:首页 > 编程语言 > C语言/C++

C++中使用STL的hashmap

2015-11-06 23:34 246 查看
我们就来分析一下hash_map的教程:

简单变量作为索引:

整形,实性,指针型,

hash_map<int, int >inthash;

inthash[1] = "123";

inthash[2] = "456";

int val = inthash[1];

int val = inthash[2];

hash_map<const char*, int >charhash;

charhash["a"] = 123;

charhash["b"] = 456;

char szinput[64] = "";

scanf("%s", szinput);

int val = charhash[szinput];

最终的结果无论输入任何字符串否无法找到对应的整数值,因为输入的字符串指针是szinput, 和"a"或"b"字符串常量指针永远不可能相等;

解决办法如下:

首先写一个仿函数charless()继承自函数基类binary_function(当然也可以不继承)

struct charless :public binary_function(const char*, const char, bool)

{

public:

result_type operate()(const first_argument_type&_left, const second_argument_type&_right) const

{

return (stricmp(_left, _right) < 0 ? true : false);

}

};

那么有了这个仿函数,我们就可以正确的使用字符穿hash_map了;

hash_map<const char*, int, hash_map<const char *, charless>> charhash

charhash["a"] = 123;

charhash["b"] = 456;

char szinput[64] = "";

scanf("%s", szinput);

int val = charhash[szinput];

那么这个时候,简单类型的使用方法介绍完毕:

另外:微软为标准的basic_string(string 的基类)提供了hash的方法:

虽然支持string 的hash; 而hash类却没有重载运算比较符,所以以前的hash_compare仍然无法工作:

struct string_less :public binary_function<const string, const string, bool>

{

public:

result_type
operator()(const first_argument_type& _left, const second_argument_type&_right)const

{

return (_left.compare(_right) < 0 ? true : false);

}

};

好了,我们可以书写如下代码:

hash_map<int, string, compare<string, string_less>>stringhash

{

stringhash["a"] = 123;

stringhash["b"] = 456;

string strkey = "a";

int val = charhash[strkey];

}

对于微软的cstring,其重载了比较运算符,所以我么必须重写hash_compare放函数:

那么在头文件#include <atlstr.h>

中包含了 ,我们运用头文件就可以使用了;

下面我们来使用 hash_value()

inline size_t cstring_hash_value(const cstring &str)

{

size_t value = _HASH_SEED;

size_t size = str.getlength();

if (size > 0)

{

size_t temp = size / 16 + 1;

size -= temp;

for (size_t index = 0; index < size; i += temp)

{

value += (size_t)str[(int)index];

}

}

return value;

}

其次重写hash_compare()函数:

class cstring_hash_value :public hash_compare<cstring>

{

public:

size_t operator()(const cstring &_key)const

{

return
(size_t)cstring_hash_value(_key);

}

bool operator()(const cstring & string1, const cstring& string 2)

{

return (comp(string1, string2));

}

};

上面的重载忽略了对于less()仿函数的应用:

因为cstring 具有比较运算符:

那么我们可以使用默认的less仿函数,在这里映射为comn()函数好了我么可以声明新的hash_map对象了:

hash_map<cstring, int, CString_compare >cstringhash

其余的操作是一样的

首先定义:

struct ihashable

{

virtual unsigned long
hash_value()const = 0;

virtual bool operator <(const ihashable&val)const = 0;

virtual inthash&operator=(const inthash&val)const = 0;

};

让我们自己写的类都派生在这里:

class ctest :public ihashable

{

public:

int m_value;

cstring m_message;

public:

ctest()m_value(0)

{};

ctest(ctest& obj)

{

m_value = obj.m_value;

m_message = obj.m_message;

}

public:

virtual ihashable& operator
=(const ihashable& val)

{

m_value = (ctest&).m_value;

m_message = (ctest&).m_message;

return *this;

}

virtual unsigned long hash_value() const

{

return (m_value ^ 0xdeadbeef);

}

virtual
bool operator<(const ihashable&val)const

{

return (m_value < ((ctest&)val).m_value);

}

};

用这个类的对象作为hash索引工作如下:

因为接口规定了比较运算符:

所以这里可以使用标准的less放函数:

所以这里忽略

template<class _key>

class myhashcompare: public hash_compare<_key>

{

public:

size_t operator ()(const _key& __key)const{

return (_key.hash_value());

}

bool operator()(const _key&_key1, const _key&key2)

{

return true(compare(_key1, _key2);

}

};

下来就这样写:

Ctest test;

test.value = 123;

test.m_message = "this is a test
";

myhash[test] = 2005;

int val = myhash[test];

可以看到正确的数字被返回,

性能分析:

采用了内联代码和模板技术的hash_map在效率上应该是非常优秀的,但我们还需要注意如下几点:

经过查看代码,字符串索引会简单类型索引速度慢,自定义类型索引的索引的性能则和我们选择hashde 的内容有很大关系,简单为主,这是使用hash_mapde 基本原则。

可以重写hash_compair仿函数

inline size_t ptchar_hash_value(const ptchar str)

{

size_t value = _HASH_SEED;

size_t szie = _tcslen(str);

if (szie > 0)

{

size_t temp = (szie / 16) + 1;

size -= temp;

for (int index = 0; index < size; index += temp)

{

value += (size_t)str[(int)index];

}

}

return value;

}

class ptchar_hash_compare :public stdext::hash_compare<PTCHAR>

{

public:

szie_t operator()(const PTCHAR _key) const

{

return ((size_t)ptchar_hash_compare(_key);

}

bool operator()(const PTCHAR _key1,const PTCHAR _key2)

{

return (_tcscmp(_key1, _key2));

}

};

stdext::hash_map<PTCHAR, long, ptchar_hash_compare>myhash;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: