map和set
来源:互联网 发布:从底层看java中的接口 编辑:程序博客网 时间:2024/06/10 19:17
map和set是两个主要的关联容器,但是底层都是红黑树实现
map
STL中关于map的理解:
map特性是,所有元素都会根据元素的键值自动排序,map的所有元素都是pair(结构体),同时有键值key和实值value。pair的第一个元素被视为键值,第二个元素视为实值,map不允许两个元素拥有相同的键值;
pair的定义:
template<class K,class V>struct Pair{ K _first; V _second; Pair(const K&key, const V&value) :_first(key) , _second(value) {}};
一:实现一个简单的字典插入,删除,查找
void TestDic(){map<string, string> dict;//插入dict.insert(make_pair("insert", "插入"));dict.insert(make_pair("find", "查找"));dict.insert(make_pair("erase", "删除"));PrintfMap(dict);//查找map<string, string> ::iterator it = dict.find("find");if(it ==dict.end()){ cout << "no found" << endl;}else{ cout << "found" << endl;}//删除map<string, string> ::iterator it1 = dict.find("erase");if (it1 == dict.end()){ cout << "no found" << endl;}else{ dict.erase(it1);}PrintfMap(dict);}
二:map统计计数(TopK问题)
如:最喜欢吃的水果:
void TestTopk(){ //方法一: map<string, int> CountMap; string fruits[] = { "苹果", "葡萄", "梨", "香蕉", "葡萄", "苹果", "葡萄", "苹果", "葡萄", "苹果", "苹果", }; for (size_t i = 0; i < sizeof(fruits)/sizeof(fruits[0]); ++i) { map<string, int>::iterator ret = CountMap.find(fruits[i]); if (ret != CountMap.end()) { ret->second++; } else//第一次出现 { CountMap.insert(make_pair(fruits[i], 1)); } }}
方法一的特点效率低,如果不存在,查找了两次;
方法二:
void TestTopk(){ //调pair<iterator, bool> insert(const value_type& val); /* insert 插入成功return pair,return false表明已经有节点存在 */ /*map<string, int> CountMap; string fruits[] = { "苹果", "葡萄", "梨", "香蕉", "葡萄", "苹果", "葡萄", "苹果", "葡萄", "苹果", "苹果", }; for (size_t i = 0; i < sizeof(fruits) / sizeof(fruits[0]); ++i) { pair<map<string, int> ::iterator, bool> pr = CountMap.insert(make_pair(fruits[i], 1)); if (pr.second == false) //已经存在++计数 { pr.first->second++; } }}
方法二的比方法一的效率高,只查找了找了一次;
方法三:
void TestTopk(){ map<string, int> CountMap; string fruits[] = { "苹果", "葡萄", "梨", "香蕉", "葡萄", "苹果", "葡萄", "苹果", "葡萄", "苹果", "苹果", }; for (size_t i = 0; i < sizeof(fruits) / sizeof(fruits[0]); ++i) { CountMap[fruits[i]]++; }}
如果前年的两种比较容易理解,那么这种方法会比较那理解,它是如何实现统计计数呢?
调用operator[]来实现
V&operator[](const k&key){ return (*((this->insert(make_pair(k,mapped_typed()))).first)).second;}
我们一层一层来分析:
1:mapped_typed()相当于调用V的缺省构造函数;
2:make_pair是pair的构造函数;里面有两个参数first和second;
3: first表示是迭代器,second表示是value;
4: 插入是insert返回值是pair;*解引用;取里面的数据;
5:如果没有则进行插入,如果存在把&value的值返回;
operator[]应用插入和修改
void PrintfMap(const map<string, string>&dict){ map<string, string>::const_iterator it = dict.begin(); while (it!=dict.end()) { cout << (*it).first << ":" << it->second << endl; ++it; } cout << endl;}//operator[]的作用是插入和修改实现字典:void TestMapDict(){ map<string, string> dict; dict["sort"] = "排序"; dict["insert"] = "插入"; dict["left"] = "左边"; dict["sort"] = "***"; PrintfMap(dict);}
前面我们了解到Topk的几种算法,但我们希望统计最喜欢吃的水果的次数,按照排序跟家直观;那么怎样能够快速排序呢?
三:排序的几种常见算法:
在前面我们知道
堆排序,优先级队列;http://blog.csdn.net/f2016913/article/details/68483000
这里我们主要看map和set的实现:
1:map实现排序
void TestTopk(){ map<string, int> Countmap; string fruits[] = { "苹果", "葡萄", "梨", "香蕉", "葡萄", "苹果", "葡萄", "苹果", "葡萄", "苹果", "苹果", }; for (size_t i = 0; i < sizeof(fruits) / sizeof(fruits[0]); ++i) { Countmap[fruits[i]]++; } vector<map<string, int>::iterator> v; map<string, int>::iterator CountIt = Countmap.begin(); while (CountIt!=Countmap.end()) { v.push_back(CountIt); ++CountIt; } //仿函数 struct Compare { bool operator()(map<string, int>::iterator l, map<string, int>::iterator r) { return l->second > r->second; } }; sort(v.begin(), v.end(), Compare());}
2:Multimap实现:
void TestMultimap(){typedef multimap<string, string> Dict; typedef multimap<string, string>::iterator DictIt; Dict dict; dict.insert(make_pair("sort", "排序")); dict.insert(make_pair("sort", "排序")); dict.insert(make_pair("sort", "排序")); dict.insert(make_pair("left", "左边")); dict.insert(make_pair("left", "剩余")); DictIt it = dict.begin(); while (it!=dict.end()) { cout << it->second << " "; ++it; } cout << endl;}
multimap特性以及用法与map完全相同,唯一的差别在于:
1. 允许重复键值的元素插入容器(使用了RB-Tree的insert_equal函数)
2. 键值key与元素value的映照关系是多对多的关系
3. 没有定义[]操作运算
3:set实现:
set的特性是,所有元素会根据元素的键值自动排序,set元素不想map那样可以同时拥有实值(value)和键值(key),set元素的键值就是实值,set不允许两个相同的键值;
void Testset(){ set<int> s; s.insert(1); s.insert(1); s.insert(1); s.insert(1); s.insert(1); s.insert(4); s.insert(2); s.insert(3); s.insert(5); set<int> ::iterator it = s.begin(); while (it!=s.end()) { cout << *it << " "; ++it; } cout << endl;}
set不仅会排序,而且会去重
4:mulitiset的实现:
mulitise的特性以及用法和set完全相同,唯一的差别是允许键值的重复
void Testmultiset(){multiset<int> s; s.insert(1); s.insert(1); s.insert(1); s.insert(1); s.insert(1); s.insert(4); s.insert(2); s.insert(3); s.insert(5); set<int> ::iterator it = s.begin(); while (it!=s.end()) { cout << *it << " "; ++it; } cout << endl;}
- 关于map 和set
- Map 和 Set 容器
- map和set异同
- set和map
- List Set和Map
- map 和 set
- List、Set和Map
- map和set异同
- set和map总结
- Javascript Map和Set
- js Map和Set
- 论set和map
- js Map和Set
- set和map
- 深入map和set
- List、Set和Map
- JavaScript---map和set
- 关于set和map
- 微信红包-腾讯校招
- java 中的类和对象
- BigInteger类的使用
- POJ 1163 最大树路径
- 十分精辟的人生格言
- map和set
- 树莓派系列三(max7219 led点阵)
- 深入理解C++对象模型-对象的内存布局,vptr,vtable
- 框架之Stucts2篇----day3.1
- chrome下,http请求重复问题
- 在Android的控件布局中,有一个奇葩的 layout_weight 属性
- POJ 1088 递归+记忆化搜索
- caffe训练GPU配置
- cookie是怎么被盗的