hash_set和hash_map
1.hash_set集合容器
hash_set利用链式哈希表,进行数据的插入、删除和搜索。与set容器同样,不同意插入反复键值的元素。SGIC++哈希表是一个链式的结构,由表头和一系列单链组成。表头是一个数组式的线性表,用vector向量泛化出来。每一个表头节点,称为桶(bucket),是一个指针域,指向链入的元素数据。
表头的长度为向量容器的元素个数。
哈希表中数据的遍历。迭代器从0号桶、1号桶、2号桶。······,逐一遍历每一个桶中的全部元素数据。
哈希表的数据检索,是通过哈希函数。计算出数据所存放的哈希地址。即算出数据在哪个桶的单链中,然后对单链中的每一个数据进行比較,检索出所要的数据。因此,每一个桶中的数据越少,比較的次数就越少,检索的效率越高。
实际应用中,详细将多少数据存入哈希表中是无法预先确定的,能够设定初始的哈希表长。随着数据量的增长,动态调整表长的大小。表长过长。会造成表头空间的浪费;表长过短。会造成每一个桶下面链的元素过多。导致检索效率不高。为了使每一个桶中的元素尽可能地少,SGI
C++使用质数作为表长,并且使用表长作为求余运算的模。构造哈希函数。SGI C++ STL中,用作表长的的质数预先用一个28个元素的数组给出。这28个质数足够覆盖32bit的随意表长范围。
1.1创建hash_set对象
主要有下面几种方式。
(1) hash_set()
创建一个空的hash集合容器。哈希表长取默认值193,哈希函数对象为默认的hasn<Value>。键值比較有用默认的函数对象equal_to<Value>。内存分配器也取默认值。
hash_set<int> hs;
(2) hash_set(size_type n)
从质数列表中找出第一个大于等于n的质数作为表长,创建一个空的哈希集合容器。哈希函数对象、键值比較函数对象和内存分配器也取默认值。
hash_set<int> hs(300);//创建一个表长为389的哈希集合容器对象
(3) hash_set(size_type n,consthasher&h)
用大于等于n的质数作为表长,哈希函数对象为h,创建哈希集合容器对象。
structmyHash{
size_t operator()(int x)const{return x+2;}
};
hash_set<int,myHash> hs(300,myHash());
(4) hash_set(size_type n,consthasher&h,const key_equal&k)
用大于等于n的质数作为表长。哈希函数对象为h。键值比較函数对象k。创建哈希集合容器对象。
structstrEqual{
bool operator()(const char *s1,const char*s2)const
{
return strcmp(s1,s2)==0;
}
};
hash_set<char*,hash<char*>,strEqual>hash(300,hash<char*>(),strEqual());
(5) hash_set(const hash_set&)
拷贝构造函数。
hash_set<int> hs1;
hash_set<int> hs2(hs1);
1.2元素的插入
使用insert函数进行插入,哈希集合容器不同意插入反复的元素键值,否则插入失败。
hash_set<int> hs;
hs.insert(31);
hs.insert(23);
hs.insert(193);
1.3元素的删除
利用erase、clear函数能够删除某个迭代器位置上的元素、等于某个键值的元素、迭代器区间元素和容器上的全部元素。
1.4元素的遍历
利用迭代器实现哈希集合容器内元素的遍历。
- #include <iostream>
- #include <hash_set>
- using stdext::hash_set;
- using namespace std;
- int main()
- {
- hash_set<int> hs;
- hs.insert(1);
- hs.insert(23);
- hs.insert(193);
- hash_set<int>::iterator begin,end;
- end=hs.end();
- for(begin=hs.begin();begin!=end;begin++)
- {
- cout<<*begin<<endl;
- }
- system("pause");
- return 0;
- }
注意:在vs2008中使用hash_set须要用usingstdext::hash_set;由于hash_set是vs2008的一个扩展,并没有在标准C++库中。
1.5元素的搜素
利用find函数能够实现元素的搜索。返回搜索到的元素的位置。
- #include <iostream>
- #include <hash_set>
- using stdext::hash_set;
- using namespace std;
- struct strEqual{
- bool operator()(const char* s1,const char* s2)const{
- return strcmp(s1,s2)==0;
- }
- };
- int main()
- {
- hash_set<char *,hash_set<char *>,strEqual> hs;
- hs.insert("apple");
- hs.insert("pear");
- hs.insert("banana");
- hs.insert("orange");
- //搜索元素banana
- hash_set<char*,hash_set<char*>,strEqual>::iterator i;
- i=hs.find("banana");
- cout<<"查找结果:"<<*i<<endl;
- system("pause");
- return 0;
- }
1.6其它经常使用函数
hash_set容器还有其它经常使用函数。empty、size、bucket_count、swap、resize和equal_range等函数能够获得容器的统计信息。
- #include <iostream>
- #include <hash_set>
- using stdext::hash_set;
- using namespace std;
- int main()
- {
- hash_set<int> hs;
- hs.insert(10);
- hs.insert(30);
- hs.insert(100);
- hs.insert(23);
- cout<<hs.empty()<<endl;//是否为空
- cout<<hs.size()<<endl;//统计元素个数
- cout<<hs.bucket_count()<<endl;//统计表长
- system("pause");
- return 0;
- }
2.hash_map哈希映射容器
hash_map容器与map容器相似,都是将记录型的元素依据键值的大小将其插入容器。可是,hash_map使用的数据结构是哈希表。map使用的数据结构是红黑树。
hash_map检索出来的元素是无序的,而map用迭代器遍历出来的元素是排序的,并且还提供了反向迭代器。
2.1创建hash_map对象
主要有下面几种方式。
(1) hash_map()
hash_map<int,char*> hm;
(2) hash_map(size_type n)
hash_map<int,char*> hm(300);
(3) hash_map(size_type n,consthasher& h)
struct myhash{
size_t operator()(int x)const{return x+2;}
};
hash_map<int,char*,myhash> hm(300,myhash());
(4) hash_map(size_type n,consthasher& h,const key_equal& k)
structstrequal{
bool operator()(const char* s1,const char*s2)const
{
return strcmp(s1,s2)==0;
}
};
hash_map<char*,int,hash<char*>,strequal>hm(300,hash<char*>(),strequal());
(5) hash_map(const hash_map&)
拷贝构造函数。
hash_map<int,char*> hm1;
hash_map<int,char*> hm2(hm1);
2.2元素的插入
利用insert函数能够将键值不反复的元素数据插入到容器的哈希表中。
- #include<iostream>
- #include<hash_map>
- using stdext::hash_map;
- using namespace std;
- int main()
- {
- hash_map<const char*,float> hm;
- hm["apple"]=3.6f;
- hm["orange"]=2.0f;
- hm["banana"]=1.5f;
- cout<<"苹果价格"<<hm["apple"]<<"元/斤"<<endl;
- cout<<"橘子价格"<<hm["orange"]<<"元/斤"<<endl;
- cout<<"香蕉价格"<<hm["banana"]<<"元/斤"<<endl;
- system("pause");
- return 0;
- }
注:在vs2008中使用hash_map须要用usingstdext::hash_map;由于hash_map是vs2008的一个扩展,并没有在标准C++库中。
2.3元素的删除
利用erase函数和clear函数能够实现删除某个迭代器位置上的元素、等于某个键值的元素、迭代器区间上的元素和容器的全部元素。
2.4元素的遍历
利用迭代器能够实现元素的遍历。
- #include<iostream>
- #include<hash_map>
- using stdext::hash_map;
- using namespace std;
- template<class Key, class NameType, class YearType, class AddrType>
- struct StudentRecord_tag{ //学生记录结构体
- struct StudentInfo_tag{ //学生信息结构体
- NameType name;
- YearType year;
- AddrType addr;
- };
- //提供类型信息
- typedef Key IdType;
- typedef StudentInfo_tag StudentInfo;
- //数据成员
- IdType id; //学号,键值
- StudentInfo sf; //学生信息,作映照数据
- };
- int main(void){
- //using namespace std;
- typedef StudentRecord_tag<int, char*, int, char*> StudentRecord;
- //学生数据
- StudentRecord srArray[] = { //3笔学生记录
- { 192, "李强", 21, "北京" },
- { 193, "王文", 29, "上海" },
- { 191, "张三", 38, "深圳" }
- };
- //创建hash_map容器对象hm,管理学生记录
- hash_map<StudentRecord::IdType, StudentRecord::StudentInfo> hm;
- //装入3笔学生记录
- for(int j=0; j<3; j++)
- hm[srArray[j].id]=srArray[j].sf;
- //迭代器遍历元素
- hash_map<StudentRecord::IdType, StudentRecord::StudentInfo>::iterator i,iend;
- iend=hm.end();
- cout << "学号 " << "姓名 " << "年龄 " << "地址 " << endl; //Tab键分隔
- for(i=hm.begin(); i!=iend; i++)
- cout << (*i).first << ' '
- << (*i).second.name << ' '
- << (*i).second.year << ' '
- << (*i).second.addr << ' '
- << endl;
- system("pause");
- return 0;
- }
2.5元素的搜索
利用find函数能够搜索扫某个元素的位置。若不存在,则返回一个结束元素的位置。
// hash_map<StudentRecord::IdType,StudentRecord::StudentInfo>::iterator i;
i=hm.find(193);
2.6其它经常使用函数
与hash_set容器一样,hash_map提供了empty、size、bucket_count、swap、resize和equal_range等函数能够取得容器的统计数据。
- #include<iostream>
- #include<hash_map>
- using stdext::hash_map;
- using namespace std;
- int main(void){
- //using namespace std;
- hash_map<int, char> hm;
- typedef pair<hash_map<int, char>::iterator, bool> ReturnPair;
- typedef pair<int, char> InsertPair;
- ReturnPair p;
- InsertPair p1(10, 'a'), p2(20, 'c'), p3(80, 'e');
- //插入p1
- p=hm.insert(p1);
- if(!p.second) cout << "插入p1失败\n";
- //插入p2
- p=hm.insert(p2);
- if(!p.second) cout << "插入p2失败\n";
- //插入p3
- p=hm.insert(p3);
- if(!p.second) cout << "插入p3失败\n";
- //打印统计数据
- cout << hm.empty() << endl; //打印是否为空(false为0)
- cout << hm.size() << endl; //打印元素个数(3)
- cout << hm.bucket_count() << endl; //打印表长(193)
- system("pause");
- return 0;
- }
hash_set和hash_map的更多相关文章
- STL之hash_set和hash_map
Contents 1 hash_set和hash_map的创建与遍历 2 hash_set和hash_map的查找 3 建议 一句话hash_set和hash_map:它们皆由Hashtable(St ...
- 容器使用的12条军规——《Effective+STL中文版》试读
容器使用的12条军规——<Effective+STL中文版>试读 还 记的自己早年在学校学习c++的时候,老师根本就没有讲STL,导致了自己后来跟人说 起会C++的时候总是被鄙视, ...
- MMORPG大型游戏设计与开发(客户端架构 part4 of vegine)
昨天是七夕,祝大家都过的快乐,希望这句迟到的问候不会造成大家心中的困扰.这一节讲到了前端比较重要的模块,性能以及调试异常模块.一个应用的性能往往是最核心的部分,就像人身体的各个器官一样,一小部分也不能 ...
- (转载)Autodesk面试技术题解答
Autodesk面试技术题解答 By SmartPtr(http://www.cppblog.com/SmartPtr/) 近一年以来,AUTODESK的面试题在网上是闹的沸沸扬扬, ...
- Django 源码小剖: 更高效的 URL 调度器(URL dispatcher)
效率问题 django 内部的 url 调度机制说白了就是给一张有关匹配信息的表, 这张表中有着 url -> action 的映射, 当请求到来的时候, 一个一个(遍历)去匹配. 中, 则调用 ...
- 学长们的求职血泪史(C/C++/JAVA)
以下分三个方向讲解,每个方向都是一个学长独自撰稿. (一) C语言篇 C语言求职血泪史 华为(实习):机试.一面.性格测试被鄙视.优招被鄙视.普招被鄙视 锐捷:笔试.面试莫名其妙被鄙视 创新工场:笔 ...
- [GeekBand] C++11~14
一.关键字decltype 由对象得到对象的数据类型,例如 Complex a(1, 2); decltype(a) b(3, 4); declare type是让编译器去找到 ...
- c++20道面试题
摘自传智播客论坛 问1:请用简单的语言告诉我C++ 是什么?答:C++是在C语言的基础上开发的一种面向对象编程语言,应用广泛.C++支持多种编程范式 --面向对象编程.泛型编程和过程化编程. 其编程领 ...
- ZJOI2017 Day1
私のZJOI Day1 2017-3-21 07:52:53 有人在暴力膜 苟-- 富贵 无相忘 ZJOI2017交流群 133135071 如果你足够厉害 如果你足够厉害 如果你足够厉害 其实完全可 ...
随机推荐
- java开发微信公众号支付(JSAPI)
https://www.cnblogs.com/gopark/p/9394951.html,这篇文章写的已经很详细了. 下面写一下自己的思路: 1.首先下载demo,地址:https://pay.we ...
- Unity 设置窗体透明
设置窗口透明.窗口置顶.鼠标穿透 方法一. 缺点:边缘不平滑,有毛边 参考博客: 1.https://alastaira.wordpress.com/2015/06/15/creating-wi ...
- 题解 CF1037D 【Valid BFS?】
不管怎么说,这都不是道紫题吧... 这里采用的思想有点类似轻重链剖分. 我们按照每个节点在序列里面出现的顺序,把每一个节点连出去的边都排一个序. 这样(如果序列没错)肯定会按照序列的方式遍历完全图. ...
- 欢迎各位技术牛人增加Swift QQ群:343549891
急招:五年以上Swift开发经验,24个月工资.30天年假.配司机专车. 欢迎各位技术牛人增加Swift 敏捷大拇指 官方QQ群1: 报上"来自CSDN"就可以.谢谢! 訪问 大拇 ...
- poj1062 Bellman 最短路应用
昂贵的聘礼 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 41066 Accepted: 11959 Descripti ...
- thinkphp路由的作用
thinkphp路由的作用 问题 请问一下什么是thinkPHP路由,路由有什么作用?谢谢 解答 网络访问地址从来都是映射访问的,最初是这样,主机名(电脑名称)=>ip地址(如局域网192.16 ...
- 27.AngularJS 下载地址
转自:https://www.cnblogs.com/best/tag/Angular/ 各个 angular.js 版本下载: https://github.com/angular/angular. ...
- POJ 3257 DP
题意: 思路: 用vector存上本出发点能到的地方&成本&有趣指数(用结构体保存) 然后DP就好了 f[i][j]表示到了i 成本为j的有趣指数最大是多少 f[vec[i][k].e ...
- BZOJ 1193 搜索+贪心
预处理出100*100以内的最优解 贪心走日 判断是0*4还是2*4 搞定 //By SiriusRen #include <queue> #include <cstdio> ...
- Ubuntu16.04+Gnome3 锁定屏幕快捷键无效解决办法
Ubuntu16.04 桌面环境通过Ubuntu server和后安装的Gnome3 桌面环境实现,安装完以后发现锁定屏幕快捷键无效,系统设置=>键盘=>快捷中 锁屏快捷键已经存在Supe ...