19:56:13 初见和告别之间,回想只剩星星点点。——许嵩《最佳歌手》
今天话不多说,进入正题吧。
STL
STL是Standard Template Library的简称,中文名标准模板库,惠普实验室开发的一系列软件的统称。它是由Alexander Stepanov、Meng Lee和David R Musser在惠普实验室工作时所开发出来的。从根本上说,STL是一些"容器"的集合,这些"容器"有list,vector,set,map等,STL也是算法和其他一些组件的集合。这里的"容器"和算法的集合指的是世界上很多聪明人很多年的杰作。STL的目的是标准化组件,这样就不用重新开发,可以使用现成的组件。STL现在是C++的一部分,因此不用安装额外的库文件。
在C++标准中,STL被组织为下面的13个头文件:<algorithm>、<deque>、<functional>、<iterator>、<vector>、<list>、<map>、<memory.h>、<numeric>、<queue>、<set>、<stack>和<utility>。
今天要讲的主要是<vector>、<list>、<map>、<set>、<queue>、<stack>;
map
Map是STL 的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力,由于这个特性,它完成有可能在我们处理一对一数据的时候,在编程上提供快速通道。
-
如:
map<int,string> maphai;
map<char,int> maphai;
map<string,char> mapstring;
map<string,int> mapstring;
map<int,char>mapint;
map<char,string>mapchar;
-
例:
具体用法就直接看例题吧。
这道题就可以用map解决会方便很多。
#include <iostream> #include <map> #include <string> using namespace std; map<string,int> shop; int main() { int n,m,p; while(cin>>n) { string s; for(int i=1;i<=n;i++) { cin>>s; shop[s]=0; } cin>>m; while(m--) { for(int i=1;i<=n;i++) { cin>>p>>s; shop[s]+=p; } int flag=shop["memory"]; int rank=1; map<string,int>::iterator it; for(it=shop.begin();it!=shop.end();it++) { if((*it).second>flag) rank++; } cout<<rank<<endl; } shop.clear(); } return 0; }
20:13:45 初雪飘过风吹霜,是否给我一次机会重来呀。——吴亦凡《贰叁》
vector
vector是表示可变大小数组的序列容器。
就像数组一样,vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理。
本质讲,vector使用动态分配数组来存储它的元素。当新元素插入时候,这个数组需要被重新分配大小为了增加存储空间。其做法是,分配一个新的数组,然后将全部元素移到这个数组。就时间而言,这是一个相对代价高的任务,因为每当一个新的元素加入到容器的时候,vector并不会每次都重新分配大小。
函数
-
向量大小: vec.size();
-
向量最大容量: vec.max_size();
-
更改向量大小: vec.resize();
-
向量真实大小: vec.capacity();
-
向量判空: vec.empty();
-
多个元素赋值: vec.assign(); //类似于初始化时用数组进行赋值
-
末尾添加元素: vec.push_back();
-
末尾删除元素: vec.pop_back();
-
任意位置插入元素: vec.insert();
-
任意位置删除元素: vec.erase();
-
交换两个向量的元素: vec.swap();
-
清空向量元素: vec.clear();
算法
-
遍历
vector<int>::iterator it; for (it = vec.begin(); it != vec.end(); it++) cout << *it << endl; for (size_t i = 0; i < vec.size(); i++) { cout << vec.at(i) << endl; }
-
翻转(元素)
#include <algorithm>
reverse(vec.begin(), vec.end());
-
排序
#include <algorithm> sort(vec.begin(), vec.end()); //从小到大 //从大到小排序,可以采用上面反转函数,也可以采用下面方法: bool Comp(const int& a, const int& b) { return a > b; } sort(vec.begin(), vec.end(), Comp);
list
list是C++标准模版库(STL)中的部分内容。实际上,list容器就是一个双向链表,可以高效地进行插入删除元素。
使用list容器之前必须加上<vector>头文件:#include<list>;
函数(c为一个list)
-
c.begin() 返回指向链表第一个元素的迭代器。
-
c.end() 返回指向链表最后一个元素之后的迭代器。
-
c.rbegin() 返回逆向链表的第一个元素,即c链表的最后一个数据。
-
c.rend() 返回逆向链表的最后一个元素的下一个位置,即c链表的第一个数据再往前的位置。
-
operator= 重载赋值运算符。
-
c.assign(n,num) 将n个num拷贝赋值给链表c。
-
c.assign(beg,end) 将[beg,end)区间的元素拷贝赋值给链表c。
-
c.front() 返回链表c的第一个元素。
-
c.back() 返回链表c的最后一个元素。
-
c.empty() 判断链表是否为空。
-
c.size() 返回链表c中实际元素的个数。
-
c.max_size() 返回链表c可能容纳的最大元素数量。
-
c.clear() 清除链表c中的所有元素。
-
c.insert(pos,num) 在pos位置插入元素num。
-
c.insert(pos,n,num) 在pos位置插入n个元素num。
-
c.insert(pos,beg,end) 在pos位置插入区间为[beg,end)的元素。
-
c.erase(pos) 删除pos位置的元素。
-
c.push_back(num) 在末尾增加一个元素。
-
c.pop_back() 删除末尾的元素。
-
c.push_front(num) 在开始位置增加一个元素。
-
c.pop_front() 删除第一个元素。
-
c1.swap(c2); 将c1和c2交换。
list<int> a1{1,2,3,4,5}; list<int>::iterator it; for(it = a1.begin();it!=a1.end();it++){ cout << *it << " "; } cout << endl; list<int> a1{1,2,3,4,5}; list<int>::reverse_iterator it for(it = a1.rbegin();it!=a1.rend();it++){ cout << *it << " "; } list<int> a1 {1,2,3,4,5},a2; a2 = a1; list<int>::iterator it; for(it = a2.begin();it!=a2.end();it++){ cout << *it << endl; } int a[5] = {1,2,3,4,5}; list<int> a1; list<int>::iterator it; a1.assign(2,10); for(it = a1.begin();it!=a1.end();it++){ cout << *it << " "; } cout << endl; a1.assign(a,a+5); for(it = a1.begin();it!=a1.end();it++){ cout << *it << " "; } cout << endl; list<int> a1{1,2,3,4,5}; if(!a1.empty()) cout << "a1 is not empty" << endl; else cout << " a1 is empty" << endl; cout << a1.size() << endl; cout << a1.max_size() << endl; list<int> a1{1,2,3,4,5}; list<int>::iterator it; cout << "clear before:"; for(it = a1.begin();it!=a1.end();it++){ cout << *it << " "; } cout << endl; a1.clear(); cout << "clear after:"; for(it = a1.begin();it!=a1.end();it++){ cout << *it << " "; } cout << endl; list<int> a1{1,2,3,4,5}; list<int>::iterator it; cout << "insert before:"; for(it = a1.begin();it!=a1.end();it++){ cout << *it << " "; } cout << endl; a1.insert(a1.begin(),0); cout << "insert(pos,num) after:"; for(it = a1.begin();it!=a1.end();it++){ cout << *it << " "; } cout << endl; a1.insert(a1.begin(),2,88); cout << "insert(pos,n,num) after:"; for(it = a1.begin();it!=a1.end();it++){ cout << *it << " "; } cout << endl; int arr[5] = {11,22,33,44,55}; a1.insert(a1.begin(),arr,arr+3); cout << "insert(pos,beg,end) after:"; for(it = a1.begin();it!=a1.end();it++){ cout << *it << " "; } cout << endl; list<int> a1{1,2,3,4,5}; list<int>::iterator it; cout << "erase before:"; for(it = a1.begin();it!=a1.end();it++){ cout << *it << " "; } cout << endl; a1.erase(a1.begin()); cout << "erase after:"; for(it = a1.begin();it!=a1.end();it++){ cout << *it << " "; } cout << endl; list<int> a1{1,2,3,4,5}; a1.push_back(10); list<int>::iterator it; cout << "push_back:"; for(it = a1.begin();it!=a1.end();it++){ cout << *it << " "; } cout << endl; a1.pop_back(); cout << "pop_back:"; for(it = a1.begin();it!=a1.end();it++){ cout << *it << " "; } cout << endl; a1.push_front(20); cout << "push_front:"; for(it = a1.begin();it!=a1.end();it++){ cout << *it << " "; } cout << endl; a1.pop_front(); cout << "pop_front:"; for(it = a1.begin();it!=a1.end();it++){ cout << *it << " "; } cout << endl; list<int> a1{1,2,3,4,5},a2,a3; a2.swap(a1); list<int>::iterator it; cout << "a2.swap(a1):"; for(it = a2.begin();it!=a2.end();it++){ cout << *it << " "; } cout << endl; swap(a3,a2); cout << "swap(a3,a2):"; for(it = a3.begin();it!=a3.end();it++){ cout << *it << " "; } return 0;
list链表,每轮先erase报2的,再erase报3的
一定要特别注意每一轮删除之前要判断s.size()是否大于3!!!
#include <stdio.h> #include <list> using namespace std; int main() { //freopen("in.txt", "r", stdin); int n, i; list<int>s; list<int>::iterator it; int T; scanf("%d", &T); while (T--){ s.clear(); scanf("%d", &n); for (i = 1; i <= n; i++)s.push_back(i); while (s.size()>3){ for (i = 1, it = s.begin(); it != s.end();){ if (i % 2 == 0){ it = s.erase(it); i = 1; } else{ ++it; ++i; } } if (s.size() > 3){ for (i = 1, it = s.begin(); it != s.end();){ if (i % 3 == 0){ it = s.erase(it); i = 1; } else{ ++it; ++i; } } } } for (it = s.begin(); it != s.end();++it){ if (it != s.begin())printf(" "); printf("%d", *it); } printf(" "); } return 0; }
20:42:39 我这句语气原来好想你,不就是我们爱过的证据。——梁静茹《可惜不是你》
set
set是STL中一个很有用的容器,用来存储同一种数据类型的数据结构(可以称之为K的模型),基本功能与数组相似。
set与数组不同的是,在set中每个元素的值都是唯一的。
而且set插入数据时,能够根据元素的值自动进行排序。
set中数元素的值并不能直接被改变.
函数
-
begin() 返回指向第一个元素的迭代器
-
clear() 清除所有元素
-
count() 返回某个值元素的个数
-
empty() 如果集合为空,返回true(真)
-
erase() 删除集合中的元素
-
find() 返回一个指向被查找到元素的迭代器,如果没找到则返回end()
-
get_allocator() 返回集合的分配器
-
insert() 在集合中插入元素
-
lower_bound() 返回指向大于(或等于)某值的第一个元素的迭代器
-
size() 集合中元素的数目
-
swap() 交换两个集合变量
-
upper_bound() 返回大于某个值元素的迭代器
这道题的意思大概是:
比赛中互有胜负,将所有人放入一个集合中,输的人放入另外一个集合中。只有唯一1个人没有输时,才产生冠军。
#include <iostream> #include <string> #include <set> using namespace std; int main() { int n; set<string> all, lose; string Winner, loser; while(cin >> n && n != 0) { all.clear(); lose.clear(); while(n--) { cin >> Winner >> loser; all.insert(Winner); all.insert(loser); lose.insert(loser); } if(all.size() - lose.size() == 1) cout << "Yes" << endl; else cout << "No" << endl; } return 0; }
21:01:30 让我为你唱一首歌,全世界都陪你听着。——《让我为你唱首歌》
queue(stack)
队列也是一种逻辑数据结构,其具有先进先出的特性,只能在队的前端进行删除, 在队的后端进行插入。针对这种特性,可以实现一些较为复杂的逻辑。在实际应用中,部分程序也正需要这样一种顺序进出的数据处理方式。使用这样的逻辑处理方式,使得我们可以将更多精力放在如何处理顺序逻辑之外的事情,对于编程、开发来讲,提供了极大的方便。
函数
-
back()返回一个引用,指向队列的最后一个元素。
-
empty()函数返回真(true)如果队列为空,否则返回假(false)。
-
front()返回队列第一个元素的引用。
-
pop()函数删除队列的一个元素
-
push() 在末尾加入一个元素
-
size() 返回队列中元素的个数
这道题要注意有一个吸收回车符,特别容易忘。
#include<bits/stdc++.h> using namespace std; int main() { stack<char> s; int n; cin>>n; getchar(); while(n>0) { n--; while(5){ char a; a=getchar(); if(a==' '||a==' '||a==EOF) { while(s.size()) { cout<<s.top(); s.pop(); } cout<<" "; } else s.push(a); if(a==' '||a==EOF) break; } cout<<endl; } return 0; }
对每次操纵进行模仿,输出成果
#include<cstdio> #include<stack> #include<queue> #include<algorithm> using namespace std; int main(){ int a, b, c; char s[10]; scanf("%d", &a); while(a--){ scanf("%d %s", &b, s); if(s[2] == 'F'){ queue <int> que; for(int i = 0; i < b; i++){ scanf("%s", s); if(s[0] == 'I'){ scanf("%d", &c); que.push(c); } else{ if(que.empty()){ printf("None "); } else{ printf("%d ", que.front()); que.pop(); } } } } else{ stack <int> ata; for(int i = 0; i < b; i++){ scanf("%s", s); if(s[0] == 'I'){ scanf("%d", &c); ata.push(c); } else{ if(ata.empty()){ printf("None "); } else{ printf("%d ", ata.top()); ata.pop(); } } } } } return 0; }
我对你(博客)就不说再见了,毕竟也不是多想再见。21:31:22