考研复试系列——第十一节 map的使用
前言
在考研上机试题中,还是经常出现一些类如词频统计的问题的,解决这类问题通常使用哈希表,在C++的STL当然提供了对其支持,比如c++中的hash_map。
在实际做题中,我们只需要使用map就OK了 。map与hashmap的用法基本一致,但底层实现是不同的,前者使用红黑树实现,后者使用哈希表实现。
当然在做题中直接map就足够了。所以这里只记录下map的使用方法。
map基础
#pragma warning(disable:4786)//消除4786警告 #include<iostream> #include<string> #include<map> using namespace std; int main() { string str = "wangcan"; reverse(str); map<string,int> mmap; //插入数据 mmap.insert(map<string,int>::value_type("wang",10)); mmap.insert(pair<string,int>("wwww",5)); mmap.insert(make_pair<string,int>("cumt",77)); mmap["csdn"] = 3; //查找数据 int n = mmap["csdn"]; map<string,int>::iterator iter; iter = mmap.find("csdn");//find返回一个迭代器 int m = iter->second;//利用迭代器获取m的值 for(iter=mmap.begin();iter!=mmap.end();iter++)//利用迭代器遍历 cout<<iter->first<<":"<<iter->second<<endl; //修改数据 mmap["csdn"] = 10; iter = mmap.find("csdn"); iter->second = 10; return 0; //删除数据 mmap.erase("cumt");//根据键值删除 mmap.erase(iter);//利用迭代器删除 mmap.clear();//清空所有 }
例题一
下面来一道以前做过的ACM的map的水题 。题目描述:
程序员Astar不仅热爱编程, 也热爱运动, 最近,他所在的公司准备组织大家开展一些体育活动, 在此之前希望了解每个人所喜欢的体育运动有哪些, 担任这次活动统计的程序员Astar要求参与投票的每个人写上自己最喜爱的3项体育运动, 并在最终结果中选出3项最受欢迎的(喜爱人数最多的前3名)作为这次活动准备开展的运动, 如果前3名中出现票数相同的, 则字母序较小的优先选择。
输入:输入的第一行有一个正整数n (n <= 100), 接下来的每一行有3个不相同的非空字符串(每个字符串只由小写字母构成, 且长度都不大于10),
代表了参与投票的人喜爱的3项运动。
输出 :按字母序的先后顺序输出一行最受欢迎的前三项运动, 每两项之间由一个空格隔开。
sample input:
3
tennis basketball golf
tennis football basketball
badminton tennis chess
sample input:
3
tennis basketball golf
tennis football basketball
badminton tennis chess
sample output:
badminton basketball tennis
代码如下:
#pragma warning(disable:4786) #include<iostream> #include<algorithm> #include<map> #include<string> using namespace std; bool cmp(const string a,const string b) { return a < b; } int main() { map<string,int> mmap; map<string,int>::iterator iter; int m,i; cin>>m; string str[3]; while(m--) { cin>>str[0]>>str[1]>>str[2]; for(i=0;i<3;i++) { iter = mmap.find(str[i]); if(iter == mmap.end())//查找不到 mmap[str[i]] = 1; else mmap[str[i]]++; } } int value[3]; for(i=0;i<3;i++) { iter = mmap.begin(); str[i] = iter->first; value[i] = iter->second;//保存最大值,其实题目并没有要求记录这个 iter++; for(;iter!=mmap.end();iter++) { if(iter->second > value[i])//后者值大的话 { str[i] = iter->first; value[i] = iter->second; } else if(iter->second == value[i])//两者值相等的话 { if(iter->first < str[i])//比较字典序 { str[i] = iter->first; value[i] = iter->second; } } } mmap.erase(str[i]);//删除已经找到的最大元素 } sort(str,str+3,cmp);//按字典需排列 cout<<str[0]<<" "<<str[1]<<" "<<str[2]<<endl; return 0; }是不是发现有了map解决这类问题简单了很多。
例题二
题目描述:
哈利波特在魔法学校的必修课之一就是学习魔咒。据说魔法世界有100000种不同的魔咒,哈利很难全部记住,但是为了对抗强敌,他必须在危急时刻能够调用任何一个需要的魔咒,所以他需要你的帮助。
给你一部魔咒词典。当哈利听到一个魔咒时,你的程序必须告诉他那个魔咒的功能;当哈利需要某个功能但不知道该用什么魔咒时,你的程序要替他找到相应的魔咒。如果他要的魔咒不在词典中,就输出“what?”
输入:
首先列出词典中不超过100000条不同的魔咒词条,每条格式为:
[魔咒] 对应功能
其中“魔咒”和“对应功能”分别为长度不超过20和80的字符串,字符串中保证不包含字符“[”和“]”,且“]”和后面的字符串之间有且仅有一个空格。词典最后一行以“@END@”结束,这一行不属于词典中的词条。
词典之后的一行包含正整数N(<=1000),随后是N个测试用例。每个测试用例占一行,或者给出“[魔咒]”,或者给出“对应功能”。
输出:
每个测试用例的输出占一行,输出魔咒对应的功能,或者功能对应的魔咒。如果魔咒不在词典中,就输出“what?”
sample input:
[expelliarmus] the disarming charm
[rictusempra] send a jet of silver light to hit the enemy
[tarantallegra] control the movement of one's legs
[serpensortia] shoot a snake out of the end of one's wand
[lumos] light the wand
[obliviate] the memory charm
[expecto patronum] send a Patronus to the dementors
[accio] the summoning charm
@END@
4
[lumos]
the summoning charm
[arha]
take me to the sky
sample output:
light the wand
accio
what?
what?
哈利波特在魔法学校的必修课之一就是学习魔咒。据说魔法世界有100000种不同的魔咒,哈利很难全部记住,但是为了对抗强敌,他必须在危急时刻能够调用任何一个需要的魔咒,所以他需要你的帮助。
给你一部魔咒词典。当哈利听到一个魔咒时,你的程序必须告诉他那个魔咒的功能;当哈利需要某个功能但不知道该用什么魔咒时,你的程序要替他找到相应的魔咒。如果他要的魔咒不在词典中,就输出“what?”
输入:
首先列出词典中不超过100000条不同的魔咒词条,每条格式为:
[魔咒] 对应功能
其中“魔咒”和“对应功能”分别为长度不超过20和80的字符串,字符串中保证不包含字符“[”和“]”,且“]”和后面的字符串之间有且仅有一个空格。词典最后一行以“@END@”结束,这一行不属于词典中的词条。
词典之后的一行包含正整数N(<=1000),随后是N个测试用例。每个测试用例占一行,或者给出“[魔咒]”,或者给出“对应功能”。
输出:
每个测试用例的输出占一行,输出魔咒对应的功能,或者功能对应的魔咒。如果魔咒不在词典中,就输出“what?”
sample input:
[expelliarmus] the disarming charm
[rictusempra] send a jet of silver light to hit the enemy
[tarantallegra] control the movement of one's legs
[serpensortia] shoot a snake out of the end of one's wand
[lumos] light the wand
[obliviate] the memory charm
[expecto patronum] send a Patronus to the dementors
[accio] the summoning charm
@END@
4
[lumos]
the summoning charm
[arha]
take me to the sky
sample output:
light the wand
accio
what?
what?
#pragma warning(disable:4786) #include<iostream> #include<map> #include<string> using namespace std; int main() { char cstr[100]; map<string,string> mmap1;//记录魔咒-解释 map<string,string> mmap2;//记录解释-魔咒 map<string,string>::iterator iter;//迭代器 while(gets(cstr)) { string sstr(cstr); if(sstr == "@END@") break; int index = sstr.find(']'); string sstr1 = sstr.substr(0,index+1);//先记录[和] string sstr2 = sstr.substr(index+2);//除去空格 //cout<<sstr1<<":"<<sstr2<<endl; mmap1[sstr1] = sstr2; mmap2[sstr2] = sstr1.substr(1,sstr1.length()-2);//解释-魔咒中魔咒不含[和] } int n; cin>>n; gets(cstr);//在cin后面跟着gets的话gets会把cin的\n识别为字符串,所以进入循环之前先输入一次(环境vc6) while(n--) { gets(cstr); string str(cstr); if(str[0] == '[')//说明是魔法要查定义 { iter = mmap1.find(str); if(iter != mmap1.end())//如果找到 cout<<mmap1[str]<<endl; else cout<<"what?"<<endl; } else//说明是定义要查魔法 { iter = mmap2.find(str); if(iter != mmap2.end()) cout<<mmap2[str]<<endl; else cout<<"what?"<<endl; } } return 0; }这里之所以没有使用getline直接读入string,是因为在我的编译环境中(vc6)发现使用getline需要两次回车才能读入一个字符串。在高版本的vs中没有这个问题。