温故篇之STL_map,set的一些应用
Posted 寻找星空的孩子
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了温故篇之STL_map,set的一些应用相关的知识,希望对你有一定的参考价值。
【知识点】
1、Set是一种关联容器,它用于存储数据,并且能从一个数据集合中取出数据。它的每个元素的值必须唯一,而且系统会根据该值来自动将数据排序。每个元素的值不能直接被改变。【重点】内部结构采用红黑树的平衡二叉树。multiset 跟set 类似,唯一的区别是允许键值重复!!!
Map是c++的一个标准容器,她提供了很好一对一的关系,在一些程序中建立一个map可以起到事半功倍的效果,总结了一些map基本简单实用的操作!
2、map的功能
自动建立Key - value的对应。key 和 value可以是任意你需要的类型。
根据key值快速查找记录,查找的复杂度基本是Log(N),如果有1000个记录,最多查找10次,1,000,000个记录,最多查找20次。
快速插入Key -Value 记录。
快速删除记录
根据Key 修改value记录。
遍历所有记录。
3、使用map
使用map得包含map类所在的头文件
#include <map> //注意,STL头文件没有扩展名.h
map对象是模板类,需要关键字和存储对象两个模板参数:
std:map<int,string> personnel;
这样就定义了一个用int作为索引,并拥有相关联的指向string的指针.
为了使用方便,可以对模板类进行一下类型定义,
typedef map<int,CString> UDT_MAP_INT_CSTRING;
UDT_MAP_INT_CSTRING enumMap;
4、在map中插入元素
改变map中的条目非常简单,因为map类已经对[]操作符进行了重载
enumMap[1] ="One";
enumMap[2] ="Two";
.....
这样非常直观,但存在一个性能的问题。插入2时,先在enumMap中查找主键为2的项,没发现,然后将一个新的对象插入enumMap,键是2,
值是一个空字符串,插入完成后,将字符串赋为"Two";该方法会将每个值都赋为缺省值,然后再赋为显示的值,如果元素是类对象,则开销比较大。
我们可以用以下方法来避免开销:
enumMap.insert(map<int,CString> :: value_type(2,"Two"))
enumMap.insert(pair<int,string>(102,"aclive"));
5、查找并获取map中的元素
下标操作符给出了获得一个值的最简单方法:
CString tmp =enumMap[2];
但是,只有当map中有这个键的实例时才对,否则会自动插入一个实例,值为初始化值。
我们可以使用Find()和Count()方法来发现一个键是否存在。
查找map中是否包含某个关键字条目用find()方法,传入的参数是要查找的key,在这里需要提到的是begin()和end()两个成员,
分别代表map对象中第一个条目和最后一个条目,这两个数据的类型是iterator.
int nFindKey= 2;//要查找的Key
//定义一个条目变量(实际是指针)
UDT_MAP_INT_CSTRING::iterator it=enumMap.find(nFindKey);
if(it== enumMap.end())
//没找到
else
//找到
通过map对象的方法获取的iterator数据类型是一个std::pair对象,包括两个数据 iterator->first和 iterator->second分别代表关键字和存储的数据
6.从map中删除元素
移除某个map中某个条目用erase()
该成员方法的定义如下:
iterator erase(iterator it);//通过一个条目对象删除
iterator erase(iterator first,iterator last)//删除一个范围
size_type erase(const Key&key);//通过关键字删除
clear()就相当于enumMap.erase(enumMap.begin(),enumMap.end());
7.map中的swap用法
Map中德swap不是一个容器中的元素交换,而是两个容器的交换;
8.map中的sort问题
Map中的元素是自动按Key升序排序,所以不能对map用sort函数;
9. map的基本操作函数:
C++ Maps是一种关联式容器,包含“关键字/值”对
begin() 返回指向map头部的迭代器
clear() 删除所有元素
count() 返回指定元素出现的次数
empty() 如果map为空则返回true
end() 返回指向map末尾的迭代器
equal_range() 返回特殊条目的迭代器对
erase() 删除一个元素
find() 查找一个元素
get_allocator() 返回map的配置器
insert() 插入元素
key_comp() 返回比较元素key的函数
lower_bound() 返回键值>=给定元素的第一个位置
max_size() 返回可以容纳的最大元素个数
rbegin() 返回一个指向map尾部的逆向迭代器
rend() 返回一个指向map头部的逆向迭代器
size() 返回map中元素的个数
swap() 交换两个map
upper_bound() 返回键值>给定元素的第一个位置
value_comp() 返回比较元素value的函数
今天看到map的时候想到了二维图,然后一时忘了怎么创。。。哎,居然写成了map<map<string,string>,int>;怎么说呢,这个其实并不是二位图,还是等于map<struct T,int>,so...真正的二维图:map<string,map<string,int> >;
要练手的可以做下经典题:
链接: http://acm.hdu.edu.cn/showproblem.php?pid=1263
水果
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 7191 Accepted Submission(s): 2817
Problem Description 夏天来了~~好开心啊,呵呵,好多好多水果~~
Joe经营着一个不大的水果店.他认为生存之道就是经营最受顾客欢迎的水果.现在他想要一份水果销售情况的明细表,这样Joe就可以很容易掌握所有水果的销售情况了.
Input 第一行正整数N(0<N<=10)表示有N组测试数据.
每组测试数据的第一行是一个整数M(0<M<=100),表示工有M次成功的交易.其后有M行数据,每行表示一次交易,由水果名称(小写字母组成,长度不超过80),水果产地(小写字母组成,长度不超过80)和交易的水果数目(正整数,不超过100)组成.
Output 对于每一组测试数据,请你输出一份排版格式正确(请分析样本输出)的水果销售情况明细表.这份明细表包括所有水果的产地,名称和销售数目的信息.水果先按产地分类,产地按字母顺序排列;同一产地的水果按照名称排序,名称按字母顺序排序.
两组测试数据之间有一个空行.最后一组测试数据之后没有空行.
Sample Input
1 5 apple shandong 3 pineapple guangdong 1 sugarcane guangdong 1 pineapple guangdong 3 pineapple guangdong 1
Sample Output
guangdong |----pineapple(5) |----sugarcane(1) shandong |----apple(3)
Source 浙江工业大学第四届大学生程序设计竞赛
写了两个,真假二维图了,/汗
//注意:两组测试数据之间有一个空行.最后一组测试数据之后没有空行.
#include<cstring>
#include<string>
#include<cstdio>
#include<iostream>
#include<map>
using namespace std;
int main()
int N,M;
scanf("%d",&N);
while(N--)
scanf("%d",&M);
string addr,future;
int num=0;
map<map<string,string>,int> salesInfo;
for(int i=0;i<M;i++)
cin>>future>>addr>>num;
map<string,string> info;
info[addr] = future;
salesInfo[info] += num;
map<map<string,string>,int>::iterator iter;
addr = "";
for(iter = salesInfo.begin();iter!=salesInfo.end();iter++)
//cout<<"("<<iter->second<<")"<<endl;
map<string,string> info(iter->first);
map<string,string>::iterator itm;
itm = info.begin();
if(addr != (*itm).first)
addr = (*itm).first;
cout<<addr<<endl;
cout<<" |----"<<(*itm).second<<"("<<iter->second<<")"<<endl;
if(N) cout<<endl;
return 0;
二维map的应用
//真正二维map...
#include<cstring>
#include<string>
#include<cstdio>
#include<iostream>
#include<map>
using namespace std;
int main()
int N,M;
scanf("%d",&N);
while(N--)
scanf("%d",&M);
string addr,future;
int num=0;
map<string,map<string,int> > salesInfo;//这才是真的二维map
for(int i=0;i<M;i++)
cin>>future>>addr>>num;
salesInfo[addr][future] += num;
map<string,map<string,int> >::iterator iter;
for(iter = salesInfo.begin();iter!=salesInfo.end();iter++)
cout<<iter->first<<endl;
map<string,int>::iterator itm;
for(itm = (iter->second).begin();itm != (iter->second).end();itm++)
cout<<" |----"<<(*itm).first<<"("<<(*itm).second<<")"<<endl;
if(N) cout<<endl;
return 0;
练的不过瘾,可以温习下下面两题
Let the Balloon Rise
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 122783 Accepted Submission(s): 48360
Problem Description Contest time again! How excited it is to see balloons floating around. But to tell you a secret, the judges' favorite time is guessing the most popular problem. When the contest is over, they will count the balloons of each color and find the result.
This year, they decide to leave this lovely job to you.
Input Input contains multiple test cases. Each test case starts with a number N (0 < N <= 1000) -- the total number of balloons distributed. The next N lines contain one color each. The color of a balloon is a string of up to 15 lower-case letters.
A test case with N = 0 terminates the input and this test case is not to be processed.
Output For each case, print the color of balloon for the most popular problem on a single line. It is guaranteed that there is a unique solution for each test case.
Sample Input
5 green red blue red red 3 pink orange pink 0
Sample Output
red pink/题意:给N个气球,求出现最多次数的颜色,保证答案唯一,N=0 break;
//解:map<string,int> 即可
#include<map>
#include<cstring>
#include<string>
#include<cstdio>
#include<iostream>
using namespace std;
int main()
int N;
while(scanf("%d",&N)!=EOF)
if(N==0) break;
map<string,int> color;
string str,MoreColor;
int mmax = -1;
for(int i=0;i<N;i++)
cin>>str;
color[str]++;
if(color[str] > mmax)
mmax = color[str];
MoreColor = str;
cout<<MoreColor<<endl;
return 0;
What Are You Talking About
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 102400/204800 K (Java/Others)Total Submission(s): 23494 Accepted Submission(s): 7875
Problem Description Ignatius is so lucky that he met a Martian yesterday. But he didn't know the language the Martians use. The Martian gives him a history book of Mars and a dictionary when it leaves. Now Ignatius want to translate the history book into English. Can you help him?
Input The problem has only one test case, the test case consists of two parts, the dictionary part and the book part. The dictionary part starts with a single line contains a string "START", this string should be ignored, then some lines follow, each line contains two strings, the first one is a word in English, the second one is the corresponding word in Martian's language. A line with a single string "END" indicates the end of the directory part, and this string should be ignored. The book part starts with a single line contains a string "START", this string should be ignored, then an article written in Martian's language. You should translate the article into English with the dictionary. If you find the word in the dictionary you should translate it and write the new word into your translation, if you can't find the word in the dictionary you do not have to translate it, and just copy the old word to your translation. Space(' '), tab('\\t'), enter('\\n') and all the punctuation should not be translated. A line with a single string "END" indicates the end of the book part, and that's also the end of the input. All the words are in the lowercase, and each word will contain at most 10 characters, and each line will contain at most 3000 characters.
Output In this problem, you have to output the translation of the history book.
Sample Input
START from fiwo hello difh mars riwosf earth fnnvk like fiiwj END START difh, i'm fiwo riwosf. i fiiwj fnnvk! END
Sample Output
hello, i'm from mars.
i like earth!
Hint
Huge input, scanf is recommended.
题意:是翻译。START--END 中间是字典翻译和需要翻译的原文; 翻译成英文,字典里没有的原样输出
//用map<string,string>做一个转换表
这里要注意是:整个book行数比较多之前我是开string[10005]数组的,结果一直RE后来我一句句输出,不存才过,之后我又存了个vector<string> 也过得了,看需求吧~
#include<cstdio>
#include<iostream>
#include<map>
#include<cstring>
#include<string>
using namespace std;
int main()
string sta;
cin>>sta;
if(sta.compare("START") == 0)
map<string,string> dictionary;//火星文字典...
string eng,marks;
while(cin>>eng)
if(eng.compare("END") == 0) break;
cin>>marks;
dictionary[marks] = eng;
string str, essay;// 这里essay不好定长度,之前定[1005]开小了,//ACCESS_VIOLATION
char ch[15];
gets(ch);//吸收回车
int cnt = 0;
while(getline (cin, str, '\\n'))
//cout<<"essay["<<cnt<<"] = "<<str<<endl;
if(str.compare("END") == 0) break;
if(str.compare("START") == 0) continue;
int len = str.size();
//str[len] = '\\n';
str.append("\\n");
//cout<<"len = "<<len<<endl;
string tmp("");
for(int i=0;i<=len;i++)
if(!(str[i] >= 'a' && str[i] <= 'z' || str[i] == '\\''))//标点 空格 换行 标签 (只有小写字母)
//cout<<"tmp = "<<tmp<<" ["<<str[i]<<"]"<<endl;
if(tmp!="" && dictionary[tmp] != "") tmp = dictionary[tmp];
essay += tmp + str[i];
tmp.clear();
else
tmp += str[i];
cout<<essay;
essay.clear();
//cout<<"essay["<<cnt<<"] = "<<essay[cnt]<<endl;
cnt++;
//for(int i=0;i<cnt;i++)
//
// cout<<essay[i]<<endl;
//
return 0;
解法二:
#include<cstdio>
#include<iostream>
#include<map>
#include<vector>
#include<cstring>
#include<string>
using namespace std;
int main()
string sta;
cin>>sta;
if(sta.compare("START") == 0)
map<string,string> dictionary;//火星文字典...
string eng,marks;
while(cin>>eng)
if(eng.compare("END") == 0) break;
cin>>marks;
dictionary[marks] = eng;
string str, essay;// 这里essay不好定长度,之前定[1005]开小了,//ACCESS_VIOLATION
vector<string> book;//统一输出
char ch[15];
gets(ch);//吸收回车
int cnt = 0;
while(getline (cin, str, '\\n'))
//cout<<"essay["<<cnt<<"] = "<<str<<endl;
if(str.compare("END") == 0) break;
if(str.compare("START") == 0) continue;
int len = str.size();
//str[len] = '\\n';
str.append("\\n");
//cout<<"len = "<<len<<endl;
string tmp("");
for(int i=0;i<=len;i++)
if(!(str[i] >= 'a' && str[i] <= 'z' || str[i] == '\\''))//标点 空格 换行 标签 (只有小写字母)
//cout<<"tmp = "<<tmp<<" ["<<str[i]<<"]"<<endl;
if(tmp!="" && dictionary[tmp] != "") tmp = dictionary[tmp];
essay += tmp + str[i];
tmp.clear();
else
tmp += str[i];
//cout<<essay;
book.push_back(essay);
essay.clear();
//cout<<"essay["<<cnt<<"] = "<<essay[cnt]<<endl;
cnt++;
for(vector<string>::iterator iter = book.begin();iter != book.end();iter++)
cout<<*iter;
return 0;
另外还有更快的解法。字典树
也附一份代码
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct node
struct node *child[26];
char *str;
;
struct node *root = new struct node;
void Init()
for(int i =0;i <26; i++)
root->child[i] = 0;
void Insert(char *c1,char *c2)
int len = strlen(c2);
struct node *cur;
cur = root;
for(int i =0;i <len;i ++)
if(cur ->child[c2[i] - 'a'] != 0)
cur = cur ->child[c2[i] - 'a'];
else
struct node *newnode = new struct node;
cur ->child[c2[i] - 'a'] = newnode;
for(int j =0; j <26; j++)
newnode ->child[j] = 0;
newnode ->str = NULL; //相当重要啊!!!!!
cur = newnode;
cur->str = (char *)malloc(15 * sizeof(char));
strcpy(cur->str, c1);
void Print(char *c2)
int len = strlen(c2);
struct node *cur;
cur = root;
if(!len) return ;
for(int i =0;i <len; i++)
if(c2[i] < 'a' || c2[i] > 'z' || cur ->child[c2[i] - 'a'] == 0)
printf("%s",c2);
return ;
else
cur = cur ->child[c2[i] - 'a'];
if(cur ->str != NULL)
printf("%s",cur ->str);
else
printf("%s",c2);
int main()
char s[15],temp[3005],c1[15],c2[15];
Init();
scanf("%s", temp);
while(scanf("%s", c1) && strcmp(c1, "END")!=0)
scanf("%s", c2);
Insert( c1, c2);
scanf("%s", temp);
getchar();
while(gets(temp) && strcmp(temp,"END")!=0)
int len = strlen(temp);
int start = -1, end = 0;
int num = 0;
for(int i =0; i<len; i++)
if(temp[i] >= 'a' && temp[i] <= 'z')
if(start == -1)
start = i;
s[num++] = temp[i];
else
if(start > -1)
start = -1;
s[num] = '\\0';
num = 0;
Print(s);
printf("%c", temp[i]);
if(start > -1)
s[num] = '\\0';
Print(s);
if(temp[len - 1] < 'a' || temp[len - 1] > 'z')
printf("%c", temp[len - 1]);
printf("\\n");
return 0;
以上是关于温故篇之STL_map,set的一些应用的主要内容,如果未能解决你的问题,请参考以下文章