STL之hash_map
来源:互联网 发布:中国8个一线城市 知乎 编辑:程序博客网 时间:2024/05/29 14:23
hash_map简介(下列在VS2010下测试)
hash_map的用法和map是一样的,提供了insert,size,count等操作,并且里面的元素也是以pair类型来存贮的。虽然对外部提供的函数和数据类型是一致的,但是其底层实现是完全不同的,map底层的数据结构是rb_tree而,hansh_map却是哈希表来实现的。
总体来说,hash_map 查找速度会比map快,而且查找速度基本和数据量大小无关,属于常数级别;而map的查找速度是log(n)级别。hash还有hash函数的耗时。当有100w条记录的时候,map也只需要20次的比较,200w也只需要21次的比较!所以并不一定常数就比log(n)小!
hash_map对空间的要求要比map高很多,所以是以空间换时间的方法,而且,对应hash_map,如果hash函数和hash因子选择不好的话,也许不会达到你要的效果,所以至于用map,还是hash_map,从3个方面来权衡:查找速度,数据量,内存使用,还有一个就是你的经验!没有特别的标准。
hash_map类在头文件hash_map中,和所有其它的C++标准库一样,头文件没有扩展名。如下声明:
#include <hash_map>
using namespace std;
using namespace stdext;
hash_map是一个聚合类,它继承自_Hash类,包括一个vector,一个list和一个pair,其中vector用于保存桶,list用于进行冲突处理,pair用于保存key->value结构,简要地伪码如下:
class hash_map<class _Tkey, class _Tval>
{
private:
typedef pair<_Tkey, _Tval> hash_pair;
typedef list<hash_pair> hash_list;
typedef vector<hash_list> hash_table;
};
另外可以通过重写 hash_compair仿函数,更改里面关于桶数量的定义,如果取值合适,也可以得到更优的性能。而且如果你的数据是自定义的类型,必须要重写这个仿函数。可以模仿原来的写法,所有的成员函数,成员变量一个不能少!
简单的一个列子,其使用方法和map是一样的:
#include <iostream>#include <hash_map>#include <string>using namespace std; int main(){ hash_map<int,string>hmap;//定义一个实例 hmap.insert(pair<int,string>(10,"hashMap"));//插入一个pair对象 hmap.insert(hash_map<int,string>::value_type(34,"test"));//value_type就是pair类型的 hmap[23] = "23"; hmap[33] = "33"; hmap[-1] = "-1"; cout<<"begin-->end:"<<endl; hash_map<int,string>::iteratorit = hmap.begin(); while(it!=hmap.end())//遍历 { cout<<it->first<<"\t"<<it->second<<endl; it++; } cout<<"find:"<<endl; it = hmap.find(-1);// 查找 if(it!=hmap.end()) { cout<<it->first<<"\t"<<it->second<<endl; it++; } cout<<"size:"<<endl; cout<<hmap.size()<<endl; cout<<"count:"<<endl; cout<<hmap.count(58)<<endl; cout<<"empty:"<<endl; cout<<hmap.empty()<<endl; system("pause"); return 0;}
简单变量作为索引:整形、实性、指针型:
#include <iostream>#include <hash_map>using namespace std; /*写一个仿函数CharLess,继承自仿函数基类binary_function *当然也可以不继承,这样写只是符合标准,而且写起来比较方便,不用被类似于指针的指针和指针的引用搞晕*/struct CharLess : publicbinary_function<const char*, const char*,bool>{public: result_type operator()(const first_argument_type& _Left,const second_argument_type& _Right)const { return(stricmp(_Left,_Right) < 0 ?true :false); }}; int main(){ hash_map<constchar*,int,hash_compare<constchar*,CharLess>> CharHash; CharHash["b"]= 456; CharHash["a"]= 123; charszInput[64] = "c"; CharHash[szInput] = 564; hash_map<constchar*,int,hash_compare<constchar*,CharLess>>::iterator iter=CharHash.begin(); while(iter!=CharHash.end()) { cout<<iter->first<<" "<<iter->second<<endl; iter++; } system("pause"); return 0;}
用户自定义类型:比如对象类型,结构体:
#include <iostream>#include <hash_map>#include <string>using namespace std; struct string_less : publicbinary_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); }}; int main(){ hash_map<string, int, hash_compare<string, string_less>>StringHash; StringHash["a"]= 123; StringHash["b"]= 456; string strKey = "c"; StringHash[strKey]; hash_map<string, int, hash_compare<string,string_less>>::iterator iter=StringHash.begin(); while(iter!=StringHash.end()) { cout<<iter->first<<" "<<iter->second<<endl; iter++; } system("pause"); return 0;}
PS:
如何用hash_map替换程序中已有的map容器?
这个很容易,但需要你有良好的编程风格。建议你尽量使用typedef来定义你的类型:
typedef map<Key,Value> KeyMap;
当你希望使用hash_map来替换的时候,只需要修改:
typedefhash_map<Key, Value> KeyMap;
其他的基本不变。当然,你需要注意是否有Key类型的hash函数和比较函数。
常用的字符串类CString类型:
#include <hash_map>#include <atlstr.h>//CString头文件#include <iostream> using namespace std;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 idx = 0; idx <= size; idx += temp) { value +=(size_t)str[(int)idx]; } } return(value);} class CString_hash_compare : publichash_compare<CString>{public: size_t operator()(const CString& _Key)const { return((size_t)CString_hash_value(_Key)); } bool operator()(constCString& _Keyval1, const CString& _Keyval2)const { return(comp(_Keyval1, _Keyval2)); }}; int main(){ hash_map<CString, int, CString_hash_compare> CStringHash; CStringHash["12"]= 12; CStringHash["13"]= 13; hash_map<CString, int, CString_hash_compare>::iterator iter=CStringHash.begin(); while(iter!=CStringHash.end()) { cout<<iter->first<<" "<<iter->second<<endl;//CString :cout在Unicode模式下不显示字符串 iter++; } system("pause"); return 0;}
自定义对象的使用方法:
#include <hash_map>#include <atlstr.h>//CString头文件#include <iostream>using namespace std; //接口中规定了比较运算符,所以这里可以使用标准的less仿函数,所以这里忽略template<class_Tkey> class MyHashCompare : publichash_compare<_Tkey> { public:/* enum { // parameters for hash table bucket_size = 4, // 0 < bucket_size min_buckets = 8 // min_buckets = 2 ^^ N, 0 < N };*/ size_t operator()(const _Tkey& _Key)const{ return(_Key.hash_value()); } bool operator()(const_Tkey& _Keyval1, const _Tkey& _Keyval2)const { return(comp(_Keyval1, _Keyval2)); } }; struct IHashable //接口{ virtualunsignedlonghash_value()const = 0; virtualbooloperator< (const IHashable& val)const = 0; virtualIHashable& operator = (const IHashable& val) = 0;}; class CTest : publicIHashable{public: intm_value; CString m_message;public: CTest() : m_value(0) {} CTest(constCTest& obj) { m_value = obj.m_value; m_message = obj.m_message; } public: virtualIHashable& operator = (const IHashable& val) { m_value = ((CTest&)val).m_value; m_message = ((CTest&)val).m_message; return(*this); } virtualunsignedlonghash_value()const { //这里使用类中的m_value域计算hash值,也可以使用更复杂的函数计算所有域总的hash值 return(m_value^0xdeadbeef); } virtualbooloperator< (const IHashable& val)const { return(m_value< ((CTest&)val).m_value); }}; int main(){ CTest test; test.m_value = 123; test.m_message = "This is a test"; hash_map<CTest,int,MyHashCompare<CTest>> MyHash; MyHash[test] = 2010; hash_map<CTest,int,MyHashCompare<CTest>>::iteratoriter=MyHash.begin(); while(iter!=MyHash.end()) { wcout<<(iter->first).m_value<<(LPCTSTR)((iter->first).m_message);// LPCTSTR转换 wcout<<" "<<iter->second<<endl; //cout<<MyHash[test]<<endl; iter++; } system("pause"); return 0;}
如何在hash_map中加入自己定义的类型:要做两件事,定义hash函数,定义等于比较函数。
#include <hash_map>#include <string>#include <iostream> using namespace std;class ClassA{public: ClassA(inta):c_a(a){} intgetvalue()const {returnc_a;} voidsetvalue(int a){c_a;}private: intc_a;}; struct hash_A{ enum { // parameters for hash table bucket_size = 4, // 0 < bucket_size min_buckets = 8 // min_buckets = 2 ^^ N, 0 < N }; //1 definethe hash function size_t operator()(constclass ClassA& A)const{ // return hash<int>(A.getvalue()); returnA.getvalue(); } //2 definethe equal function bool operator()(const class ClassA & a1, constclass ClassA & a2)const{ return a1.getvalue() < a2.getvalue(); }}; int main(){ hash_map<ClassA, string, hash_A>hmap; ClassA a1(12); hmap[a1]="Iam 12"; ClassA a2(198877); hmap[a2]="Iam 198877"; cout<<hmap[a1]<<endl; cout<<hmap[a2]<<endl; system("pause"); return 0;}
//use a map to create a phone directory#include <iostream>#include <map>#include <cstring>using namespace std; class name{private: charstr[40];public: name() {strcpy(str,"");} name(char*s) {strcpy(str,s);} char*get() {return str;}}; //mustdefine less than relative to name objectsbool operator<(namea,name b){ returnstrcmp(a.get(),b.get()) < 0;} class phoneNum{private: charstr[80];public: phoneNum(){strcpy(str,"");} phoneNum(char*s){strcpy(str,s);} char*get(){return str;}}; int main(){ map<name,phoneNum> directory; //put namesand numbers into map directory.insert(pair<name,phoneNum>(name("Tom"),phoneNum("555-4533"))); directory.insert(pair<name,phoneNum>(name("Chris"),phoneNum("555-9678"))); directory.insert(pair<name,phoneNum>(name("John"),phoneNum("555-8195"))); directory.insert(pair<name,phoneNum>(name("Rachel"),phoneNum("555-0809"))); //given aname,find number charstr[80]; cout << "entername: "; cin >> str; map<name,phoneNum>::iterator p; p = directory.find(name(str)); if(p !=directory.end()) cout << "phone number: " <<p->second.get()<<endl; else cout << "name not in directory"<<endl; system("pause"); return 0;}
- STL之hash_map详解
- STL之hash_map总结
- STL之hash_map
- STL之hash_map
- stl之hash_map
- STL 之 hash_map源码剖析
- STL hash_map
- STL---hash_map
- STL hash_map
- stl-hash_map
- STL之红黑树容器:set,hash_set,multiset,hash_map,multimap
- STL源码剖析——关联容器之hash_map
- 详细解说STL hash_map
- 详细解说STL hash_map
- STL:map与hash_map
- STL hash_map使用
- STL hash_map使用
- STL中的hash_map
- poj 3280
- Apache + Tomcat集群
- 腾讯2013年实习生笔试题目(附答案) C++版
- Cocos2dx输出Log的两种方法
- 把字符串按字典顺序排序
- STL之hash_map
- Hibernate错误 Caused by: org.hibernate.PropertyNotFoundException: Could not find a getter for pnsame i
- awk用法详解
- 越来越烦
- 更适合学习的产品级cortex-A9 安卓开发板
- system property
- 下载就这么难吗?
- Old Calculator
- POJ2236——Wireless Network