第三种方式:借助计数排序思想,使用operator[ ]运算符重载获取value
mapped_type& operator[] (const key_type& k);//返回k对应的value的引用
返回:
(*((this->insert(make_pair(k,mapped_type()))).first)).second
即:
1. mapped_type& operator[](const key_type& k) 2. { 3. pair<iteerator, bool> ret = insert(make_pair(k, mapped_type())); 4. return ret.first->second; 5. }
operator[ ]的本质就是插入:
①如果k不在map中,先插入<k,V( )>,返回节点中V对象的引用
②如果k已经在map中,返回k所在节点中对应V对象的引用
1. //第三种统计方法-计数排序 2. string arr[] = { "篮球","足球","排球","羽毛球","足球","乒乓球","足球","排球","羽毛球","篮球","足球" }; 3. map<string, int> countMap; 4. 5. for (const auto& str : arr) 6. { 7. countMap[str]++;//等价于countMap.operator[](str),会调用mapped type()的默认构造函数构造一个匿名对象。其中str是key,++的是key对应的value,即返回值 8. } 9. 10. for (const auto& e : countMap) 11. { 12. cout << e.first << ":" << e.second << endl; 13. }
这三种方式中,operator[ ]最简洁,更好使用。
计数结束后,排序有2种方式:
第一种排序:用sort排序
可以使用sort进行排序,先包含sort的头文件:
#include<algorithm>
vector里面如果要存pair,得把每个pair拿出来拷贝,再插入到vector中,而且string是深拷贝,代价大。
sort要排序,必须支持整数比较大小,传的是迭代器,迭代器指向的数据必须要能比较大小,v里面存的是pair,需要重载pair的比较大小。 sort的第3个参数是compare,要传对象,用实际对象推compare的类型,可以用仿函数比较,给sort的第3个参数传个匿名对象
sort的第3个参数是Compare比较方式,默认是按小于比较的,要找排名前面的球类,必须要传入大于的比较方式,就需要重新写仿函数:
1. template <class RandomAccessIterator, class Compare> 2. void sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp);
大于的比较方式的仿函数:
1. struct MapItCompare 2. { 3. bool operator()(map<string, int>::iterator x, map<string, int>::iterator y) 4. { 5. return x->second > y->second; 6. } 7. };
1. void Map_test2() 2. { 3. string arr[] = { "篮球", "足球", "排球", "羽毛球", "足球", "乒乓球", "足球", "排球", "羽毛球", "篮球", "足球" }; 4. 1.统计计数 5. map<string, int> countMap; 6. for (const auto& str : arr) 7. { 8. countMap[str]++; 9. } 10. 11. 2.排序(第一种用sort排序) 12. vector<map<string, int>::iterator> v; 13. map<string, int>::iterator countMapIt = countMap.begin(); 14. 15. while (countMapIt != countMap.end()) 16. { 17. v.push_back(countMapIt);//把迭代器放进vector中,不创建节点,不拷贝新数组 18. countMapIt++; 19. } 20. sort(v.begin(), v.end(), MapItCompare()); 21. }
统计计数完毕后:
排序完毕后:
这就找出了排名前3的球类。
第二种排序:用map排序:map这个结构是天生的可以用来排序的结构,不过map的比较方式默认是less,也就是按照升序排的:
1. template < class Key, // map::key_type 2. class T, // map::mapped_type 3. class Compare = less<Key>, // map::key_compare 4. class Alloc = allocator<pair<const Key,T> > // map::allocator_type 5. > class map;
但是现在需要按照降序排,就要传比较方式:
1. //第二种排序,借助map排序 2. map<int, string,greater<int>> sortMap;//将次数作为first,将字符串作为second,比较方式为大于greater 3. for (auto e : countMap) 4. { 5. sortMap.insert(make_pair(e.second, e.first)); 6. }
由于int作为key,所以有相同key的球类只存第一种,篮球、排球和羽毛球的个数都是2(举的例子有点不恰当,应该往所有球类的个数都不相同),只会出现篮球,不会出现排球和羽毛球:
这种方式用了拷贝,如果不想拷贝的话,可以存到set中。
第三种排序方式:
给set的迭代器传个仿函数:
1. // 利用set排序 --不拷贝pair数据 2. set<map<string, int>::iterator, MapItCompare> sortSet;//set传模板参数,传MapItCompare类型 3. countMapIt = countMap.begin(); 4. while (countMapIt != countMap.end()) 5. { 6. sortSet.insert(countMapIt); 7. ++countMapIt; 8. }
第四种比较方式: 用优先级队列,向优先级队列中存放迭代器,减少拷贝,要找个数最大的,要建小堆
1. struct MapItCompare 2. { 3. bool operator()(map<string, int>::iterator x, map<string, int>::iterator y) 4. { 5. return x->second < y->second; 6. } 7. };
1. typedef map<string, int>::iterator MapIt; 2. priority_queue<MapIt, vector<MapIt>, MapItCompare> pq; 3. 4. map<string, int>::iterator countMapIt = countMap.begin(); 5. while (countMapIt != countMap.end()) 6. { 7. pq.push(countMapIt); 8. countMapIt++; 9. }
堆顶元素就是找到的个数最多的球类,足球:
(4)删除erase( )
size_type erase (const key_type& k);//通过k删除
1. map<string, string> dict; 2. dict.insert(make_pair("spring", "春天")); 3. dict["spring"] += "、温泉"; 4. dict["summer"] = "夏天"; 5. dict["autumn"] = "秋天"; 6. dict["winter"] = "冬天"; 7. 8. auto mit = dict.begin();//同map<string, int>::iterator mit = m.begin(); 9. while (mit != dict.end()) 10. { 11. cout << mit->first << ":" << mit->second << endl; 12. mit++; 13. } 14. cout << endl;
dict.erase("spring");
再遍历打印:
四、multiset 和 multimap
set中和map中存储的元素不可以重复,但是multiset和multimap中的元素是可以重复的,它们中的元素不可以修改,但是可以插入和删除:
multiset:头文件为#include<set>
1. template < class T, // multiset::key_type/value_type 2. class Compare = less<T>, // multiset::key_compare/value_compare 3. class Alloc = allocator<T> > // multiset::allocator_type 4. > class multiset;
1. multiset<int> mls1; 2. int arr[] = { 2,3,2,5,3,3}; 3. 4. mls1.insert(arr, arr + 6); 5. for (auto e : mls1) 6. { 7. cout << e << endl; 8. }
允许存在key相同的元素:
multimap:头文件为#include<map>
1. template < class Key, // multimap::key_type 2. class T, // multimap::mapped_type 3. class Compare = less<Key>, // multimap::key_compare 4. class Alloc = allocator<pair<const Key,T> > // multimap::allocator_type 5. > class multimap;
1. multimap<string,string> mlp1; 2. mlp1.insert(make_pair("spring", "春天")); 3. mlp1.insert(make_pair("summer", "夏天")); 4. mlp1.insert(make_pair("autumn", "秋天")); 5. mlp1.insert(make_pair("winter", "冬天")); 6. 7. mlp1.insert(make_pair("spring", "温泉")); 8. 9. for (auto e : mlp1) 10. { 11. cout << e.first << ":" << e.second << endl; 12. }
允许存在key相同的pair: