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

C++ STL学习笔记十二 hash_map映照容器

2015-10-12 20:18 573 查看
/*

*

************************************************************************************

* hash_map映照容器的基础说明:

************************************************************************************

*

* hash_map哈希映照容器:使用hash表的数据结构,插入的元素键值不允许重复

* hash_map的所有元素都是pair:第一元素为键值(key),不能修改;第二元素为实值(value),可被修改

*

* 不提供反向迭代器,只有前向迭代器iterator和const_iterator

* 可定义出操作符[]

*

* Hashed Associative Container Pair Associative Container Unique Associative Container

*

* 目前还不是C++的标准容器,只是SGI C++ STL的一个扩展容器

* 使用hash_map必须使用宏语句#include <hash_map>

* 可与map作比较: hash_map检索时使用的键值比较次数少,容器需占用较多的空间,用迭代器遍历出来的元素是非排序的;

* map则使用链表的二分法进行检索,空间使用率高,遍历出来的元素是排序的,而且可提供反向迭代器。

*

**************************************************************************************

*

* 创建map对象:

* 1.hash_map<char,int> a; //键值类型为char,映照数据类型为int,默认表长为193

* 2.hash_map(size_type n); //hash_map<char,int> a(300);此时表长为389

* * 3.hash_map(size_type n,const hasher& h);

* * 4.hash_map(size_type n,const hasher& h,const key_equal& k);

* 5.hash_map(const hash_map&);

*

* //Example4:

* struct strequal{

* bool operator() (const char* a,const char* b) const {

* return strcmp(a,b)==0;}

* };

* hash_map<char*,int,hash<char*>,strequal> hm(300,hash<char*>(),strequal());

*

**************************************************************************************

*

* 元素的插入

* //typedef pair<const key,T> value_type;

* pair<iterator,bool> insert(const value_type& v);

* void insert(first,last);

*

**************************************************************************************

*

* 元素的删除

* void erase(iterator pos);

* size_type erase(const key_type& k); //删除等于键值k的元素

* void erase(first,last); //删除[first,last)区间的元素

* void clear();

*

**************************************************************************************

*

* 访问与搜索

*

* iterator begin();iterator end(); //企图通过迭代器改变元素是不被允许的

*

* iterator find(const key_type& k) const;

* pair<iterator,iterator> equal_range(const key_type& k) const; //此时键值不允许重复,故没有太大用途

*

* 其它常用函数

* bool empty() const;

* size_type size() const;

* size_type bucket_count(const key_type& k) const; //获得hash表的表长

* void swap();

* resize();

* void swap();

*

* iterator lower_bound();iterator upper_bound();pair<iterator,iterator> equal_range();//上界、下届、确定区间

*

*

*

********************************************

** cumirror ** tongjinooo@163.com ** **

********************************************

*

*/

#include <string>

#include <hash_map>

#include <iostream>

using namespace std;

template<class Key,class NameType,class AgeType,class AdressType>

struct StudentRecord_tag{ //学生记录结构体

struct StudentInfo_tag{

NameType name;

AgeType age;

AdressType city;

};

typedef Key IdType;

typedef StudentInfo_tag StudentInfo;

IdType id;

StudentInfo stuinfo;

};

//针对最后的示例,设置的hash函数

struct myhash{

size_t operator() (const string& str) const

{

unsigned long __h = 0;

for (size_t i = 0 ; i < str.size() ; i ++)

__h = 5*__h + str[i];

return size_t(__h);

}

};

class str_compare{

public:

bool operator()(const string& str1,const string& str2)const

{

return str1==str2;

}

};

int main(){

// 使用[]操作符

hash_map<string,int> animal;

animal[string("fish")]=12;

animal[string("dog")]=10;

animal[string("cat")]=5;

cout<<animal["cat"]<<endl;

// 结构体A中定义的结构体B,在结构体A外可以使用吗?

// StudentInfo_tag a; //直接这样是无法使用的,若想独立使用可以参照下面的方法

// typedef StudentRecord_tag<int,char*,int,char*> StudentRecorda;

// StudentRecorda::StudentInfo_tag testa;

typedef StudentRecord_tag<int,char*,int,char*> StudentRecord;

StudentRecord stuArray[]={

{192,"黄庆",23,"北京"},

{191,"童进",23,"长沙"},

{194,"饺子",23,"福州"},

{193,"小芳",23,"宁波"},

};

// 此处应该留意typedef的使用

hash_map<StudentRecord::IdType,StudentRecord::StudentInfo> school;

typedef pair<const StudentRecord::IdType,StudentRecord::StudentInfo> value_type;

for(int i=0;i<4;i++){

value_type p(stuArray[i].id,stuArray[i].stuinfo);

school.insert(p);

}

// 测试是否插入成功

cout<<school[193].name<<endl;

// 采用迭代器访问,注意map类型容器,其元素为pair类型,pair中first/second要明白

hash_map<StudentRecord::IdType,StudentRecord::StudentInfo>::iterator j;

cout<<"同学"<<" "<<"住址"<<endl;

for(j=school.begin();j!=school.end();j++){

cout<<j->second.name<<" "<<

j->second.city<<endl;

}

// 其它函数示例

// 元素的重复插入

value_type p(stuArray[0].id,stuArray[0].stuinfo);

pair<hash_map<const StudentRecord::IdType,StudentRecord::StudentInfo>::iterator,bool> insertReturn;

cout<<(

(insertReturn=school.insert(p)).second==true?"插入成功":"插入失败"

)

<<endl;

cout<<"总人数:"<<school.size()<<endl;

cout<<"hash表长:"<<school.bucket_count()<<endl;

// 如下思考:

// 上例中key:IdType为int型,故不用定义hash函数对象,也可将IdType定为string类型,形如"0120504140227"这样的类型

// 此时需要定义hash函数,具体解法如下:(在原来定义的变量名后+1)

// 原想在上面例子的基础上进行改进,但不成功,可能与string类型内存分配模式有关

// typedef StudentRecord_tag< string,char*,int,char*> StudentRecord1;

// StudentRecord1 stuArray1[]={ //不好意思,你们暂时先入我班吧

// {string("0120504140208"),"黄庆",23,"北京"},

// {string("0120504140227"),"童进",23,"长沙"},

// {string("0120504140209"),"饺子",23,"福州"},

// {string("0120504140216"),"小芳",23,"宁波"},

// };

// hash_map<StudentRecord1::IdType,StudentRecord1::StudentInfo,myhash> school1;

// typedef pair<const StudentRecord1::IdType,StudentRecord1::StudentInfo> value_type1;

// for(int i=0;i<4;i++){

// value_type1 p(stuArray1[i].id,stuArray1[i].stuinfo);

// school.insert(p);

// }

// 在网上看到一份较为简单的例子,根据自己的稍稍改了下(注意前面的hash函数与比较函数)

hash_map<string,string,myhash,str_compare> myHash;

string strArray[][2]={

{"0120504140227","童进"},

{"0120504140236","zyl"},

{"0120504140216","hq"},

{"0120504140209","jz"},

};

typedef pair<string,string> value_type2;

for(int k=0;k<4;k++){

value_type2 p(strArray[k][0],strArray[k][1]);

myHash.insert(p);

}

hash_map<string,string,myhash,str_compare>::iterator p1;

for(p1=myHash.begin();p1!=myHash.end();p1++){

cout<<p1->first<<" "<<

p1->second<<endl;

}

return 0;

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