## map 一个程序 ```c++ #include "bits/stdc++.h" #include #include using namespace std; map mp; int main(){     int n;     cin>>n;     while (n--) {         int x=2;         while(x--){             long long a;             cin>>a;             if(mp.find(a)==mp.end()){                 mp[a]=1;             }             else{                 mp[a]=mp.find(a)->second+1;             }         }     } //  for(auto it:mp){ //      cout<maxnum){             maxnum=it.second;             maxi=it.first;         }     }     for(auto it:mp){         if(maxnum==it.second){             cont++;         }     }     cout<    //stl头文件不带.h 初始化 map list1; map list2 =     {{1,"java教程"},{2,"c++教程"},{3,"python教程"}}; map list3 =     {pair (1,"java教程"),pair (2,"c++教程")}; 添加对象 map list1; list1.insert(pair (1,15)); list1.insert({2,13}); //两种方式添加元素 注意:map中key的值是唯一的,如果插入一个已经存在的key值会导致原先值的覆盖,请尽量避免这样。 mp[a]++; 不存在某人0开始 遍历 //遍历整个list1 for (auto iter = list1.begin(); iter != list1.end(); ++iter) {                      cout << iter->first << "  " << iter->second << endl;     } map::iterator it;     for (it = mp.begin(); it != mp.end(); it++) {         cout <first << " " << it->second ;     } for(auto it:mp){         cout <first << " " << it->second ;     } 删除 list1.erase(1);    //括号内为key值,也就是左值 修改 类似数组方法修改 查找 可以直接通过key值查找,如果要通过value值找ksy的话需要借助find函数 map list1 =       {{1,12},{2,15},{3,18},{4,22}}; cout<first;    //输出1 cout<second;    //输出12 当所查找的关键key出现时,它返回数据所在对象的位置,如果沒有,返回iter与end函数的值相同。 末尾 // find 返回迭代器指向当前查找元素的位置否则返回map::end()位置 iter = mapStudent.find("123"); if(iter != mapStudent.end())        cout<<"Find, the value is"<second< map_1; map_1.clear();                //清除所有元素 map_1.empty();                //如果为空返回1,负责返回0 map_1.size();                 //返回容器的元素个数  map的大小 map_1.max_size;               //返回容器可以容纳的最大元素 //可以用过迭代器与first,second访问元素 map_1.begin()->first;         //结果为容器的第一个元素的key值 map_1.begin()->second;         //结果为容器的第一个元素的value值 smallpoint 一个错误 C++ ERROR : base operand of ‘->’ has non-pointer type ‘std::pair< int, int>’ 的解释 list> cachelist; unordered_map>::iterator> map; void put(int key, int value) {     auto it = map.find(key);     if(it != map.end()){         touch(it->second);         it->second->second = value; // ①     }     else if(map.size() < cap){         cachelist.push_front(make_pair(key,value));         map[key]=cachelist.begin();     }     else{         auto it = cachelist.back();// ②         map.erase(it->first); // 出错位置~~!!         cachelist.pop_back();         cachelist.push_front(make_pair(key,value));         map[key]=cachelist.begin();     } } 报错内容: Line xx: base operand of '->' has non-pointer type ' std::pair ' 分析与解决 首先unordered_map的erase() 函数的参数可以是键值,可以是迭代器,也可以是迭代器区间,那么肯定不是erase()的问题; 然后报错提示告诉我们pair不能用->符号,那就奇怪了,位置①我们不是也用了it->second->second吗?①处的it是unordered_map的iterator,it->second是list>的iterator,所以it->second->second是pair的第二值,好像没什么不对?? 到这里可能你跟我一样,发现问题了,②处的it并不是list>的迭代器,而是cachelist的最后一个元素节点的地址,auto实际上应该是pair &,而pair是不认识->符号的,所以出错位置的应该把->改成.,即: map.erase(it.first); int的最大值等问题 cout< using namespace std; //读入数据 //不会读取空格 void getter(){     string a;     while (cin>>a) {         cout<> v(ma.begin(), ma.end());    //定义一个pair类型的数组,并且数组第一个数据为ma的第一个数据,最后一个数据为ma的最后一个数据 sort(v.begin(), v.end(), cmp);    //将v从v 的第一个到最后一个数据根据自定义的比较函数cmp进行分类。sort的自定义比较函数之后会说 //来自C++Reference的样例 int myints[] = {32,71,12,45,26,80,53,33};   std::vector myvector (myints, myints+8);               // 32 71 12 45 26 80 53 33 (对前八个数排序)   std::sort (myvector.begin(), myvector.begin()+4);           //(12 32 45 71)26 80 53 33 (对前四个数排序) pair(对组) pair是C++定义的模板类型,可以同时存储两个类型的数据,其实可以用结构体实现的呢 pair a    //定义 a.firts="Hello World";    //对第一个数据进行操作 a.second="3";             //对第二个数据进行操作 map 先来看看C++reference的定义 /* Maps are associative containers that store elements formed by a combination of a key value and a mapped value, following a specific order. In a map, the key values are generally used to sort and uniquely identify the elements, while the mapped values store the content associated to this key. The types of key and mapped value may differ, and are grouped together in member type value_type, which is a pair type combining both: */ typedef pair value_type; 其实,我们可以把map理解为一个容器,其内部存的是一组键值对,即两个不同类型的数据。 可以理解为“关键字”以及“关键字的值”(没错,和pair很像) vector(容器) vector可以看成加强版数组,用于储存相同类型的多个数据。这里要介绍他的排序函数sort() 从C++reference中可以找到以下例子  int myints[] = {32,71,12,45,26,80,53,33};   std::vector myvector (myints, myints+8);               //初始化为 32 71 12 45 26 80 53 33(myints的前八个放入vector)   // using default comparison (operator <):   std::sort (myvector.begin(), myvector.begin()+4);           //(12 32 45 71)26 80 53 33   // using function as comp   std::sort (myvector.begin()+4, myvector.end(), myfunction); // 12 32 45 71(26 33 53 80)   // using object as comp   std::sort (myvector.begin(), myvector.end(), myobject);     //(12 26 32 33 45 53 71 80) 可以看出sort()其实可以自己加函数进行排序,不过如果自己每加的话就默认非降序排列。 那如果我要自己加函数要怎么加呢? 参考:【C++】从最简单的vector中sort用法到自定义比较函数comp后对结构体排序的sort算法 首先自定义比较函数的返回值是bool型的,这里给出一个例子     bool comp(int a,int b){         return a>b;     }     sort(v.begin(), v.end(), comp); 比较时sort函数根据comp函数进行判断输的大小,系统默认ab时返回为真,那么最终得到的排序结果也相应的从小到大变成从大到小。其实可以这样理解:排序结束后,a是前面的数,b是后面的数,我们的自定义函数是为了定义a与b的关系 再让我们来看代码中的例子 bool cmp(pair a, pair b) {     bool result = false;     if (a.second == b.second&&a.first < b.first) {         result = true;     }     else if (a.second > b.second) {         result = true;     }     return result; } sort(v.begin(), v.end(), cmp); 那么上述式子就表明,对vector中的第一个数据到最后一个数据排列。 因为vector中的数据类型是pair,根据自定义的比较函数,当pair的second(词语出现次数)相等时,first(单词)小的在前面(若有并列,则按递增字典序输出)。 代码 ```c++ #include #include #include #include #include using namespace std; bool cmp(pair a, pair b); int main() {     char ch;     string s;   //字符串用于记录一个单词     map ma;    //map记录词频,string代表的单词出现次数为int     do {         ch = getchar();         //当读到的是合法字符(大小写字母、数字下划线)         if ((ch >= 'a'&&ch <= 'z') || (ch >= 'A'&&ch <= 'Z') || (ch >= '0'&&ch <= '9') || ch == '_') {             if (s.size() <= 14) {   //当长度为14时再进行一次接入,长度为15就停止接入                 if (ch >= 'A'&&ch <= 'Z') {     //把大写换成小写                     ch += 32;                 }                 s += ch;    //把单个字符ch接到字符串s后,string中有运算符重载所以加法表示接在后面             }         }         else {      //当不是合法字符就表示这个词读取结束了,出现次数+1             if (s.size() > 0) {                 ma[s]++;             }             s.clear();      //清空字符串以统计下一个单词         }         if (ch == '#') {    //读到#退出循环             break;         }     } while (ch != '#');     vector> v(ma.begin(), ma.end());        //存储pair的一个数组(把vector理解为增强版的数组)     sort(v.begin(), v.end(), cmp);     cout << v.size() << endl;     int cnt = (int)(ma.size()*0.1);     for (int i = 0; i < cnt; i++) {         cout << v[i].second << ":" << v[i].first << endl;     }     return 0; } //利用pair数据,每个pair数据都含有一个string数值和int数值 // bool cmp(pair a, pair b) {     bool result = false;     if (a.second == b.second&&a.first < b.first) {         result = true;     }     else if (a.second > b.second) {         result = true;     }     return result; } // 附加:上述优化 bool cmp2(paira,pairb){ // 若有并列则按照递增字典序输出     if(a.second>b.second){         return true;     }     else if(a.second==b.second&&a.first set具有迭代器set::iterator i 定义一个迭代器,名为i 可以把迭代器理解为C语言的指针 set q;     //以int型为例 默认按键值升序 set> p;  //降序排列 int x; q.insert(x);    //将x插入q中 q.erase(x);     //删除q中的x元素,返回0或1,0表示set中不存在x q.clear();      //清空q q.empty();      //判断q是否为空,若是返回1,否则返回0 q.size();       //返回q中元素的个数 q.find(x);      //在q中查找x,**返回x的迭代器**,若x不存在,则返回指向q**尾部**的迭代器即 q.end() q.lower_bound(x); //返回一个迭代器,**指向第一个**键值**不小于**x的元素 q.upper_bound(x); //返回一个迭代器,指向第一个键值大于x的元素 q.rend();         //返回第一个元素的的前一个元素迭代器 q.begin();        //返回指向q中第一个元素的迭代器 q.end();         //返回指向q最后一个元素下一个位置的迭代器 q.rbegin();      //返回最后一个元素 set_name.count(element)  返回0或者1 返回值:该函数返回1或0,因为该集合仅包含唯一元素。如果设置的容器中存在该值,则返回1。如果容器中不存在它,则返回0。 举例 ```c++ #include #include using namespace std; int main() {     set q;   //默认按升序排列     q.insert(5);     q.insert(5);     q.insert(5);     cout<<"q.size "<::iterator i;     for( i=q.begin();i!=q.end();i++)   //set的遍历         cout<<*i<<" ";                 //输出1 2 3 4,可见自动按键值排序     cout<> p;  //降序排列     p.insert(1);     p.insert(2);     p.insert(3);     p.insert(4);     p.insert(5);     for(i=p.begin();i!=p.end();i++)         cout<<*i<<" ";     cout< #include using namespace std; struct node{     int a,b;     bool operator< (const node W)const     {         return a>W.a;  //按a的值升序     } }t; int main() {     set q;     t.a=1;     t.b=2;     q.insert(t);     t.a=4;     t.b=2;     q.insert(t);     t.a=3;     t.b=5;     q.insert(t);         set::iterator i;     for(i=q.begin();i!=q.end();i++)     {         t=*i;         cout< #include #include #include #include #define maxn 100 using namespace std; int main(){     set a[maxn];     int i;     for(i = 0;i< 2;i++){         for(int j = 0;j< 5;j++)     a[i].insert(j);         }     for(i = 0;i< 2;i++){         for(set::iterator it = a[i].begin();it!=a[i].end();it++){             cout << *it << " ";         }cout<<"\n";     } } ``` #### 一个题 点赞狂魔 7-3 点赞狂魔 分数 25 作者 陈越 单位 浙江大学 微博上有个“点赞”功能,你可以为你喜欢的博文点个赞表示支持。每篇博文都有一些刻画其特性的标签,而你点赞的博文的类型,也间接刻画了你的特性。然而有这么一种人,他们会通过给自己看到的一切内容点赞来狂刷存在感,这种人就被称为“点赞狂魔”。他们点赞的标签非常分散,无法体现出明显的特性。本题就要求你写个程序,通过统计每个人点赞的不同标签的数量,找出前3名点赞狂魔。 输入格式: 输入在第一行给出一个正整数N(≤100),是待统计的用户数。随后N行,每行列出一位用户的点赞标签。格式为“Name K F 1 ​  ⋯F K ​  ”,其中Name是不超过8个英文小写字母的非空用户名,1≤K≤1000,F i ​  (i=1,⋯,K)是特性标签的编号,我们将所有特性标签从 1 到 10 7   编号。数字间以空格分隔。 输出格式: 统计每个人点赞的不同标签的数量,找出数量最大的前3名,在一行中顺序输出他们的用户名,其间以1个空格分隔,且行末不得有多余空格。如果有并列,则输出标签出现次数平均值最小的那个,题目保证这样的用户没有并列。若不足3人,则用-补齐缺失,例如mike jenny -就表示只有2人。 输入样例: 5 bob 11 101 102 103 104 105 106 107 108 108 107 107 peter 8 1 2 3 4 3 2 5 1 chris 12 1 2 3 4 5 6 7 8 9 1 2 3 john 10 8 7 6 5 4 3 2 1 7 5 jack 9 6 7 8 9 10 11 12 13 14 输出样例: jack chris john ```c++ #include using namespace std; #define max 1005 struct user {     string name;     int k;     int a[1005];     int cnt; } ; user u[105]; bool cmp(user a, user b) {     if(a.cnt==b.cnt)     {         return a.kb.cnt; } vector q; void add(int x) {     if(q.size()==0)         q.push_back(x);     else     {         for(int i=0;i>N;     for(int i=0; i>u[i].name>>u[i].k;         for(int j=0; j>u[i].a[j];         }     }     for(int i=0; i