1.Map
Map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力,由于这个特性,它完成有可能在我们处理一对一数据的时候,在编程上提供快速通道。这里说下map内部数据的组织,map内部自建一颗红黑树(一种非严格意义上的平衡二叉树),这颗树具有对数据自动排序的功能,所以在map内部所有的数据都是有序的,后边我们会见识到有序的好处。
下面举例说明什么是一对一的数据映射。比如一个班级中,每个学生的学号跟他的姓名就存在着一一映射的关系,这个模型用map可能轻易描述,很明显学号用int描述,姓名用字符串描述(本篇文章中不用char *来描述字符串,而是采用STL中string来描述),下面给出map一个简单的描述代码:
Map<int, string> mapStudent;
-
- #include <map>
- #include <string>
- #include <iostream>
- using namespace std;
- int main()
- {
- map<int, string> mapStudent;
- mapStudent[1] = “student_one”;
- mapStudent[2] = “student_two”;
- mapStudent[3] = “student_three”;
- map<int, string>::iterator iter;
- for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
- {
- Cout<<iter->first<<” ”<<iter->second<<end;
- }
- }
下面由一个具体的例题来联系一下map:
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1004
这道题就是说统计气球中出现颜色最多的一种,输出颜色,用了map会发现代码简洁省时间
代码如下;
- #include<iostream>
- #include<cstdio>
- #include<map>
- using namespace std;
- int main()
- {
- int n;
- string ballon;
- while(cin>>n,n)
- {
- map<string,int> m;
- int N=n;
- while(N--)
- {
- cin >> ballon;
- m[ballon]++;
- }
- map<string,int>::iterator p;
- int maxx=0;
- string max_ballon;
- for(p=m.begin();p!=m.end();p++)
- {
- if(p->second>maxx)
- {
- maxx=p->second;
- max_ballon=p->first;
- }
- }
- cout<< max_ballon << endl;
- }
- return 0;
- }
这个简单说一下就是容器map对应这气球颜色和数量,然后用迭代器通过比较数量大小从而输出对应的颜色.
下面来一点map常用的操作函数:
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的函数
2.set
set是关联式容器。set作为一个容器也是用来存储同一数据类型的数据类型,并且能从一个数据集合中取出数据,在set中每个元素的值都唯一,而且系统能根据元素的值自动进行排序。应该注意的是set中数元素的值不能直接被改变。C++ STL中标准关联容器set, multiset, map, multimap内部采用的就是一种非常高效的平衡检索二叉树:红黑树,也成为RB树(Red-Black Tree)。RB树的统计性能要好于一般平衡二叉树,所以被STL选择作为了关联容器的内部结构。
下面还是来一个具体的例子来说明一下,接着总说一下用法
题目链接:http://codeforces.com/problemset/problem/745/A
这道题就是找循环节的个数,因为字符串的长度给的范围很小,所以直接暴力就可以了
先贴代码,再解释:
- #include<iostream>
- #include<cstdio>
- #include<vector>
- #include<algorithm>
- #include<cstring>
- #include<set>
- using namespace std;
- int main()
- {
- ios::sync_with_stdio(0);
- cin.tie(0);
- string a;
- cin>>a;
- int len=a.size();
- a+=a;
- set<string>str;
- for(int i=0;i<len;i++)
- {
- string s=a.substr(i,len);
- str.insert(s);
- }
- cout<<str.size()<<endl;
- return 0;
- }
就是先把输入的字符串克隆连接一下,然后用substr截取原长度放到set容器里面,因为set的每个值都是唯一的,所以重复的会自动覆盖,然后最后看容器里面的元素个数就可以了.
下面说一下set常用操作函数:
begin() ,返回set容器的第一个元素
end() ,返回set容器的最后一个元素后面的地址(切记不是返回最后一个元素)
clear() ,删除set容器中的所有的元素
empty() ,判断set容器是否为空
max_size() ,返回set容器可能包含的元素最大个数
size() ,返回当前set容器中的元素个数
rbegin ,返回的值和end()相同
rend() ,返回的值和rbegin()相同
常用操作函数运用:
-
-
-
- #include<iostream>
- #include<algorithm>
- #include<set>
- using namespace std;
- int main()
- {
- set<int>s;
- s.insert(1);
- s.insert(2);
- s.insert(3);
- s.insert(1);
- cout<<"set中size的值为:"<<s.size()<<endl;
- cout<<"set中maxsize的值为:"<<s.max_size()<<endl;
- cout<<"set中第一个元素是:"<<*s.begin()<<endl;
- cout<<"set中最后一个元素是:"<<*s.end()<<endl;
- s.clear();
- if(s.empty())
- {
- cout<<"set为空!!!"<<endl;
- }
- cout<<"set的size值为:"<<s.size()<<endl;
- cout<<"set的maxsize的值为:"<<s.max_size()<<endl;
- return 0;
- }
运行结果如下
:
- set中size的值为:3
- set中maxsize的值为:461168601842738790
- set中第一个元素是:1
- set中最后一个元素是:3
- set为空!!!
- set的size值为:0
- set的maxsize的值为:461168601842738790
3.vector
vector(向量): C++中的一种数据结构,确切的说是一个类.它相当于一个动态的数组,当程序员无法知道自己需要的数组的规模多大时,用其来解决问题可以达到最大节约空间的目的.其实就是用容器充当了数组.如:声明一个int向量以替代一维的数组:vector <int> a;(等于声明了一个int数组a[],大小没有指定,可以动态的向里面添加删除)。再如:用vector代替二维数组.其实只要声明一个一维数组向量即可,而一个数组的名字其实代表的是它的首地址,所以只要声明一个地址的向量即可,即:vector <int *> a.同理想用向量代替三维数组也是一样,vector <int**>a;再往上面依此类推.
还是来一道题,这个题有点难理解,但是理解了这个vector可以较好的掌握.
题目链接:http://codeforces.com/problemset/problem/747/C
题意:给定n个服务器编号1—n,q个任务,每个任务都有一个开始时间t,需要的服务器的个数k,和任务完成需要花的时间d,求每个任务完成所需要的服务器的id号的和最小是多少.
-
-
-
- #include<iostream>
- #include<algorithm>
- #include<vector>
- using namespace std;
- vector<int> jq[105];
-
- int main()
- {
- ios::sync_with_stdio(0);
- cin.tie(0);
- int n,q;
- cin>>n>>q;
- for(int i=0;i<q;i++)
- {
- int t , k , d;
- cin >> t >> k >> d;
- int sum=0;
- int w = k;
- for(int i=1;k&&i+k-1<=n;i++){
- if(jq[i].empty()||jq[i][jq[i].size()-1]<t)
- {
- k--; }
- }
- if(!k){
- k = w;
- for(int i = 1; k &&i+k-1 <= n ; i++ ){
- if(jq[i].empty()||jq[i][jq[i].size()-1]<t){
- sum+=i;
- jq[i].push_back(t+d-1);
- k--;
- }
- }
- }
- if(sum) cout<<sum<<'\n';
- else cout<<"-1"<<'\n';
- }
- return 0;
- }
这个其实也就是用vector开了一个二维数组,i代表机器的型号,然后判断每一次机器的是否空闲或者机器用完的时间是否满足其他时间的利用.下面再来一个不用vector的题解,两者比较理解.
- #include <bits/stdc++.h>
- using namespace std;
- int jq[105];
- int main() {
- ios::sync_with_stdio(0);
- cin.tie(0);
- int n, q;
- cin >> n >> q;
- for (int i = 0; i < q; i++) {
- int t, k, d;
- cin >> t >> k >> d;
- int sum = 0;
- int q = k;
- for (int i = 1; k && i + k - 1 <= n; i++) {
- if (jq[i] < t) k--;
- }
- if (!k) {
- k = q;
- for (int i = 1; k && i + k - 1 <= n ; i++) {
- if (jq[i] < t) {
- sum += i;
- jq[i] = t + d - 1;
- k--;
- }
- }
- }
- if (sum) cout << sum << '\n';
- else cout << "-1\n";
- }
- }
vector常用操作函数:
push_back 在数组的最后添加一个数据
pop_back 去掉数组的最后一个数据
at 得到编号位置的数据
begin 得到数组头的指针
end 得到数组的最后一个单元+1的指针
front 得到数组头的引用
back 得到数组的最后一个单元的引用
max_size 得到vector最大可以是多大
capacity 当前vector分配的大小
size 当前使用数据的大小
resize 改变当前使用数据的大小,如果它比当前使用的大,者填充默认值
reserve 改变当前vecotr所分配空间的大小
erase 删除指针指向的数据项
clear 清空当前的vector
rbegin 将vector反转后的开始指针返回(其实就是原来的end-1)
rend 将vector反转构的结束指针返回(其实就是原来的begin-1)
empty 判断vector是否为空
swap 与另一个vector交换数据
5.stack
stack 模板类的定义在<stack>头文件中。
stack 模板类需要两个模板参数,一个是元素类型,一个容器类型,但只有元素类型是必要
的,在不指定容器类型时,默认的容器类型为deque。
定义stack 对象的示例代码如下:
stack<int> s1;
stack<string> s2;
stack 的基本操作有:
入栈,如例:s.push(x);
出栈,如例:s.pop();注意,出栈操作只是删除栈顶元素,并不返回该元素。
访问栈顶,如例:s.top()
判断栈空,如例:s.empty(),当栈空时,返回true。
访问栈中的元素个数,如例:s.size()。
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1022
这个题就是进栈和出栈的问题
-
-
-
- #include<iostream>
- #include<algorithm>
- #include<stack>
- using namespace std;
- int main()
- {
- stack<char> s;
- int n,i,j,k,result[100];
- char str1[100],str2[100];
- while(cin>>n>>str1>>str2)
- {
- j=0,i=0,k=1;
- s.push(str1[0]);
- result[0]=1;
- while(i<n&&j<n)
- {
- if(s.size()&&s.top()==str2[j])
- {
- j++;
- s.pop();
- result[k++]=0;
- }
- else {
- if(i==n) break;
- s.push(str1[++i]);
- result[k++]=1;
- }
- }
- if(i==n) cout<<"No."<<endl;
- else
- {
- cout<<"Yes."<<endl;
- for(i=0;i<k;i++)
- {
- if(result[i])
- cout<<"in"<<endl;
- else
- cout<<"out"<<endl;
- }
- }
- cout<<"FINISH"<<endl;
- }
- return 0;
- }
5.queue
queue 模板类的定义在<queue>头文件中。
与stack 模板类很相似,queue 模板类也需要两个模板参数,一个是元素类型,一个容器类
型,元素类型是必要的,容器类型是可选的,默认为deque 类型。
定义queue 对象的示例代码如下:
queue<int> q1;
queue<double> q2;
queue 的基本操作有:
入队,如例:q.push(x); 将x 接到队列的末端。
出队,如例:q.pop(); 弹出队列的第一个元素,注意,并不会返回被弹出元素的值。
访问队首元素,如例:q.front(),即最早被压入队列的元素。
访问队尾元素,如例:q.back(),即最后被压入队列的元素。
判断队列空,如例:q.empty(),当队列空时,返回true。
访问队列中的元素个数,如例:q.size()
- #include <cstdlib>
- #include <iostream>
- #include <queue>
-
- using namespace std;
-
- int main()
- {
- int e,n,m;
- queue<int> q1;
- for(int i=0;i<10;i++)
- q1.push(i);
- if(!q1.empty())
- cout<<"dui lie bu kong\n";
- n=q1.size();
- cout<<n<<endl;
- m=q1.back();
- cout<<m<<endl;
- for(int j=0;j<n;j++)
- {
- e=q1.front();
- cout<<e<<" ";
- q1.pop();
- }
- cout<<endl;
- if(q1.empty())
- cout<<"dui lie bu kong\n";
- system("PAUSE");
- return 0;
- }