STL简介

\(STL\)是\(Standard\) \(Template\) \(Library\)的简称,中文名称为标准模板库,从根本上讲, 就是各种\(STL\)容器的集合,容器可以理解为能够实现很多功能的系统的函数。常见的容器有 vectorstackqueue mapset 等。

迭代器

迭代器( iterators )是用来访问容器中的元素,类似于指针。迭代器全部包含两个函数:

1.begin() ,返回一个容器开头的迭代器;

2.end() ,返回一个容器末尾的迭代器,但是不包括最后一个元素,而是最后一个元素的下一个地址。

定义:


  1. containers <typename>::iterators name;
  2. //containers为容器类型,typename为容器内的数据类型,name为迭代器名

string

简介

C语言中,一般使用字符数组 char str[ ] 来存放字符串,但是操作起来非常麻烦,容易出错。 在 C++ 中加入了 string 类型用来存放字符串,使用起来更加方便。

使用时,需要添加头文件 string,即 #include<string>

定义


  1. string name; // name是变量名
  2. string name2="abcde"; //可直接赋值

如果需要存放多个字符串,定义 string 类型数组:


  1. string name [N];
  2. //name[N]可以存放N个字符串。

输入输出

如果要输入输出,只能使用 cincout 。使用 cin 读入string类型,就像用 scanf() 读字符 数组一样,忽略开头的(制表符、换行符、空格),当再次碰到空字符就停止(并不会读取空字符)。


  1. string s;
  2. cin>>s;

读入时忽略了空字符,可以将其记作 cin 读字符串读的是单词。当然,有时我们更希望读取的是句子。 C++提供了 getline 函数以供使用。

getline 的原型是: getline(cin,s); cin 指的是读入流,一般情况下我们直接写 cin 即可, s 是字符串,即我们读入的东西要存放的字符串。


  1. string s;
  2. getline(cin,s); // getline()读入一行的字符,会舍弃换行符

访问

(1)通过下标访问

对于 string 类型的字符串进行访问,与字符数组访问一样,使用下标。如果有 string 类型变量名 为 s ,可直接访问对应字符 s[0]s[1]s[2]……,s[s.size()-1]s.size() 是用来求 string 类型的长度。

(2)通过迭代器访问


  1. string::iterator it

定义了 string 的迭代器 it ,可以通过 *it 访问string中的每一个字符,在常用的STL容器 中,只有 vector string 允许使用 v.begin()+5这种迭代器加上整数的写法,等价于访问s[5]。同时,迭代器可以进行自加、自减操作,即 it++++itit-- --it

例如:


  1. string s="abcdef";
  2. for(string::iterator it=s.begin();it!=s.end();it++) //输出abcdef
  3. cout<<*it<<" ";
  4. cout<<endl;
  5. for(string::iterator it=s.begin()+3;it!=s.end();it++) //输出def
  6. cout<<*it<<" ";

s.end() 不是取 s 的尾元素地址,而是尾元素地址的下一个地址,不存储任何元素,不支持 it<end()的写法。

运算

string 类型可以直接进行加法运算。但是加法是将两个字符串拼接起来。

例如:


  1. string s1="abc",s2="efgh";
  2. cout<<s1+s2; //输出abcefgh

② string 类型可以互相进行复制。

例如:


  1. string s3
  2. s3=s2
  3. cout<<s3; //输出efgh

③ string 类型可以直接进行关系运算。直接比较大小,按照字典序进行比较。


  1. if(s1>s2) cout<<1;
  2. else cout<<0; //最后结果为0,"efgh"字典序大于"abc"
  3. //判断是否相等。 s
  4. tring s1="abc",s2="abc";
  5. if(s1==s2) cout<<1; //会输出1

常用函数

① size()和length()

这两个函数都是返回 string 类型的长度(字符个数)。时间复杂度 O(1)

② clear()和empty()

clear() 用来清空 string 中的所有元素,时间复杂度为O(1) 。

empty() 用来判断 string 是否为空,是返回true,否则返回 false

例如:


  1. string s="abcde";
  2. cout<<s.size (); //输出5
  3. s.clear();
  4. cout<<s.length(); //输出0
  5. if(s.empty()) cout<<1;
  6. else cout<<0; //输出1

③ insert(pos,s2)

s 下标为 pos 的元素前插入 string 类型 s2 。 例如:


  1. string s="abcde",s2="opq";
  2. s.insert(3,s2);
  3. cout<<s; //输出abcopqde

④ erase(pos,len)

删除 s 中下标为pos 开始的len 个字符 。

例如:


  1. string s="abcdefgh";
  2. s.erase(3,3);
  3. cout<<s; //输出abcgh

⑤ find(s2)

s2 s子串时,返回在s中第一次出现的位置,否则,返回 string::npos

例如:


  1. string s="abcdefabcde",s2="cde";
  2. if(s.find(s2)!=string::npos) cout<<s.find(s2); //输出2
  3. //s.find(s2,pos),是在 s 中以 pos 位置起查找 s2 第一次出现的位置,返回值s.find(s2)相同

⑥ replace(pos,len,s2)

删除 s 中下标为 pos 开始的 len 个字符,并在下标为pos处插入s2

例如:


  1. string s1="asfgg",s2="ad";
  2. s1.replace(1,1,s2);
  3. cout<<s1<<endl; //输出aadfgg

vector

简介

vector 为变成数组,即长度可以根据需要进行改变的数组。在信息学竞赛中,有些题目需要定义很大 的数组,这样会出现"超出内存限制"的错误,使用 vector 简洁方便,还可以节省空间。

使用时,需要添加头文件 vector ,即 #include<vector>

定义


  1. vector<typename> name;

以上定义相当于定义了一个一维数组 name[size] ,只是 size 不确定,大小可以根据需要而变化。 其中 tyepename 为基本类型,如 intdoublechar 、结构体等,也可以是STL的容器,如 string queuevector 等。

例如:


  1. vector<int> a
  2. vector<double> score;
  3. vector<node> stu //node为已经定义了得结构体

但是,如果 typename 也是一个 STL 容器,那么定义时,需要在两个 ">"之间加上一个空格,因为">>"会被当作右移运算,从而导致编译出错,例如:


  1. vector<int> a[100]; //定义一个一维长度固定为100,另一维不确定的二维数组a[100][size]
  2. vector<vector<int> > a; //定义一个两维都可变的二维数组a[size][size]

常用函数

(1)push_back(x)

vector 数组后面添加一个元素x,下标从0开始,时间复杂度为 O(1)

(2)size()

如果是一维数组, size() 获得 vector 中元素的个数;如果是二维数组, size() 获得 vector 中 的第二维的元素个数,时间复杂度为 O(1)

(3)pop_back()

删除 vector 的末尾元素,时间复杂度为O(1)

(4)clear()

清空 vector 中的元素,时间复杂度为O(n) ,n 为 vector 中元素的个数。

(5)insert(it,x)

vector 迭代器 it 处插入一个元素 x , x 后的元素后移,时间复杂度为**O(n)* * .

(6)erase(it)、erase(first,last)

删除 vector 中的元素元素。erase(it),删除迭代器it处的元素; erase(first,last) ,删除左闭右开区间内的所以元素。

例如:


  1. vector<int> v;
  2. for(int i=1;i<=5;i++) v.push_back(i); //数组元素为1 2 3 4 5
  3. for(int i=0;i<v.size();i++) cout<<v[i]<<" "; //输出1 2 3 4 5
  4. cout<<endl;
  5. v.pop_back();
  6. for(int i=0;i<v.size();i++) cout<<v[i]<<" "; //输出1 2 3 4
  7. cout<<endl;
  8. v.insert(v.begin()+2,10); //将10插入到v[2]处
  9. for(int i=0;i<v.size();i++) cout<<v[i]<<" "; //输出1 2 10 3 4
  10. cout<<endl;
  11. v.erase(v.begin()+1,v.begin()+3); //删除v[1],v[2],
  12. for(int i=0;i<v.size();i++) cout<<v[i]<<" "; //输出1 3 4
  13. cout<<endl;
  14. v.clear();
  15. cout<<v.size(); //输出0

访问

访问 vector 中的元素一般有两种方式。

(1)通过下标进行访问,对于容器vector v,可以使用v[i]来访问第i个元素。

(2)通过迭代器访问

定义:


  1. vector<int>::iterator it;

定义一个迭代器 it ,通过 *it 访问 int 类型的 vector 中的元素。

在常用的容器中,只有 vector string 允许使用 v.begin()+5这种迭代器加上整数的写法。


  1. vector<int> v;
  2. for(int i=1;i<=5;i++) v.push_back(i); //数组元素为1 2 3 4 5
  3. vector<int>::iterator it=v.begin();
  4. for(int i=0;i<v.size();i++)
  5. cout<<*(it+i)<<" "; //输出1 2 3 4 5

同时,迭代器可以进行自加、自减操作,即 it++++itit----it


  1. vector<int> v;
  2. for(int i=1;i<=5;i++) v.push_back(i); //数组元素为1 2 3 4 5
  3. for(vector<int>::iterator it=v.begin();it!=v.end();it++)
  4. cout<<*it<<" "; //输出1 2 3 4 5

stack

简介

stack 翻译为栈,实现先进后出的容器。

使用时,需要添加头文件 stack ,即 #include<stack>

定义


  1. stack<typename> name

例如:


  1. stack<int> s; //定义一个int类型的栈s

常用函数

(1)psuh(x)

将元素 x 压栈,时间复杂度为 O(1)

(2)top()

获取栈顶元素,时间复杂度为O(1)

(3)pop()

弹出栈顶元素,时间复杂度为O(1)

(4)empty()

检测 stack() 是否为空,空返回 true ,否则返回 false ,时间复杂度为 。在使用 top()pop()之前,须用 q.empty() 判断是否为空,否则可能因为栈空出现错误。

(5)size()

返回 stack 内的元素个数,时间复杂度为 O(1)

例如:


  1. stack<int> s;
  2. for(int i=1;i<=5;i++) s.push(i); //栈元素为1 2 3 4 5
  3. s.pop(); //删除栈顶元素5
  4. cout<<s.top()<<endl; //输出4
  5. cout<<s.size()<<endl; //输出4
  6. while(!s.empty())
  7. {
  8. cout<<s.top(); //输出 4 3 2 1
  9. s.pop();
  10. }

queue

简介

queue 翻译为队列,是一个"先进先出"的容器。 使用时,需要添加头文件 queue ,即 #include <queue>

定义


  1. queue <typename> name; // name是变量名

例如:


  1. queue <int> q; //定义一个int类型,名为q的队列

常用函数

(1)push(x)

x入队,时间复杂度O(1)

(2)front()和back()

分别用来访问队首和队尾元素,时间复杂度O(1)

(3)pop()

删除队首元素。

(4)empty()

用来检查队首是否为空,返回 true 或者 false ,时间复杂度 。在使用front()pop() 之前,须用 empty() 判断是否为空,否则可能因为队空出现错误。

(5)size()

返回中的元素个数,时间复杂度O(1)

priority_queue

简介

priority_queue 翻译为优先队列,其底层是用堆实现的。

在优先队列中,任何时刻,队首元素一定是当前优先级最高(值最大)的一个(大根堆),也可以是值 最小的一个(小根堆)。你可以不断往队列中添加或删除优先级不同的元素,每次操作队列都会自动调 整,始终保证队首优先级最高。

优先队列的优先级设置一般是数字越大优先级越大,对于char,字典序越大优先级越大。

使用时,需要添加头文件 queue ,即 #include <queue>

定义


  1. priority_queue <typename> name;

例如:


  1. priority_queue <int> q; //定义一个int类型,名为q的优先队列:

这样定义的是一个大根堆,它的原型其实是:


  1. priority_queue <int,vector<int>,less<int> > q;

尖括号中多了两个参数, vector<int> ,表示的是承载底层数据结构——堆的容器,类型与第一个参 数一致; less ,是对第一个参数的比较类,表示数字越大优先级越大(大根堆),而如果用 greater ,则表示数字越小优先级越大。

因此,定义大根堆有两种方法,这两种方法是等价的:


  1. priority_queue <int> q;
  2. priority_queue <int,vector<int>,less<int> > q;

定义小根堆:


  1. priority_queue <int,vector<int>,greater<int> > q;

注意,最后的">>" ,两个">"之间是有空格的,没有空格会被当作右移运算,会出现编译错误。

常用函数

(1)push(x)

x入队,加入后,会自动调整整个优先 队列内部结构,保证队首(堆顶)优先级最高。

(2)top()

获取队首元素(堆顶元素),时间复杂度 O(1)

(3)pop()

删除队首元素(堆顶元素),加入后,会自 动调整整个优先队列内部结构,保证队首(堆顶)优先级最高。

(4)empty()

用来检查队首是否为空,返回 true 或者 false ,时间复杂度 O(1) 。在使用 top() pop()之前,须用 empty() 判断是否为空,否则可能因为队空出现错误。

例如:


  1. priority_queue <int,vector<int>,greater<int> > q; //定义小根堆
  2. q.push(4);
  3. q.push(6);
  4. q.push(3);
  5. q.push(9);
  6. if(!q.empty()) cout<<q.top(); //输出3
  7. q.pop();
  8. if(!q.empty()) cout<<q.top(); //输出4

结构体

如果优先队列的元素是结构体。

现在读入若干学生的语文、数学成绩和姓名,按照按语文从大到小排序,语文相同按数学大到小排序, 数学相同,按名字字典序排序。

也可以使用 pair ,更方便。

例如:


  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. struct node
  4. {
  5. int chinese;
  6. int math;
  7. string name;
  8. bool operator<(const stu &x) const{
  9. if(chinese<x.chinese) return 1; //语文大的在前,和sort相反
  10. if(chinese>x.chinese) return 0;
  11. if(math<x.math) return 1; //语文相等,数学大的在前
  12. if(math>x.math) return 0;
  13. if(name>x.name) return 1; //语文数学都相等,字典序大的在前
  14. return 0;
  15. }
  16. }a;
  17. priority_queue<node> q;
  18. int main()
  19. {
  20. a.chinese=90;a.math=80;a.name="abc";
  21. q.push(a); //放入
  22. a.chinese=90;a.math=85;a.name="xyz";
  23. q.push(a);
  24. a.chinese=90;a.math=85;a.name="yyy";
  25. q.push(a);
  26. a.chinese=92;a.math=85;a.name="bcd";
  27. q.push(a);
  28. a=q.top();
  29. cout<<a.chinese<<" "<<a.math<<" "<<a.name<<endl; //输出 92 85 bcd
  30. q.pop(); //删除第一个
  31. a=q.top();
  32. cout<<a.chinese<<" "<<a.math<<" "<<a.name<<endl; //输出 90 85 xyz
  33. return 0;
  34. }

pair

pair 是二元结构体,将两个元素捆绑在一起,相当于:


  1. struct pair
  2. {
  3. typename1 first;
  4. typename2 second;
  5. }

使用时,需要添加头文件 #include<utility>

定义

pair 有两个参数,可以是任意基本类型或容器。


  1. pair <typename1,typename2> name

初始化

pair 使用 firstsecond 访问第一,第二个元素。

pair 有三种初始化的方式,如下:


  1. pair<string,int> p("abc",1); //初始化1
  2. cout<<p.first<<" "<<p.second<<endl; //输出abc 1
  3. p.first="bcd"; //初始化2
  4. p.second=5;
  5. cout<<p.first<<" "<<p.second<<endl; //输出bcd 5
  6. p=make_pair("xyz",9); //初始化3
  7. cout<<p.first<<" "<<p.second<<endl; //输出xyz 9

如果有三个元素,也可以用 pair 实现:


  1. pair<int,pair<int,int> > p[100]; //> >中间有空格,否则会被当作位移运算
  2. p[1].first=1;
  3. p[1].second.first=5;
  4. p[1].second.second=2;
  5. cout<<p[1].first<<" "<<p[1].second.second; //输出1 2

pair 可以直接做比较。比较规则是先以 first 的大小作为标准,只有当 first 相等时才去判断 second 的大小。

例如:


  1. pair<int,int> p1(5,10);
  2. pair<int,int> p2(5,15);
  3. pair<int,int> p3(10,5);
  4. if(p1<p3) cout<<"p1<p3"<<endl; //输出p1<p3
  5. if(p1<p2) cout<<"p1<p2"<<endl; //输出p1<p2
  6. if(p1<=p3) cout<<"p1<=p3"<<endl; //输出p1<=p3make<int,int> p1(5,10);

map

简介

map 翻译为映射。其实,数组就是一种映射。int a[100]定义了一个 intint 的映射, a[5]=25 ,把 5 映射到 25 。数组总是将int类型映射到其他类型。如果要将 string 类型映射到int 类型,数组就很不方便,此时可以使用mapmap可以将任意基本类型(包括STL容器)映射 到任意基本类型(包括STL类型)。

map 常用情形:

1)建立字符(串)与整数之间的映射

2)判断大整数(几千位)或者其他类型数据是否存在,可以将map当布尔数组使用,实现类似哈希表的功 能。

3)字符串与字符串的映射。 使用时,需要添加头文件 map ,即 #include<map>

定义


  1. map<typename1,typename2> name;

typename1 是映射前的类型(键 ),typename2是映射后的类型(value值 ), name 为映射名称。

普通 int 数组 a 就是: map<int,int> a;

字符串映射到整型,必须使用 string ,不能使用charmap<string,int> a;

访问

(1)通过下标进行访问

下标访问就像访问普通数组元素一样,如定义: map<char,int> mp ,就可以通过 mp['c'] 访问对应 元素,如 mp['c']=24

(2)通过迭代器进行访问

map 的每一对映射都有两个 typename ,所以用 it->first 访问键,使用 it->second 来访问值。

赋值

map 有两种种输入方式:

(1)用insert函数插入pair数据,pair可以作为map的键值对来插入。


  1. map<string,int> mp;
  2. mp.insert(pair<string,int>("xyz",1));
  3. mp.insert(pair<string,int>("def",2));
  4. mp.insert(pair<string,int>("abc",3));
  5. for(map<string,int>::iterator it=mp.begin();it!=mp.end();it++)
  6. cout<<it->first<<" "<<it->second<<" "; //输出abc 3 def 2 xyz 1

可以看出, map 建立映射后,会自动实现按键从小到大排序,这是因为 map 内部使用红黑树实现的 (set也是如此)。

(2)用数组进行插入


  1. map<string,int> mp;
  2. mp["abc"]=1;
  3. mp["def"]=2;
  4. mp["xyz"]=3;
  5. for(map<string,int>::iterator it=mp.begin();it!=mp.end();it++)
  6. cout<<it->first<<" "<<it->second<<" "; //输出abc 1 def 2 xyz 3

但是它们是有区别的,用 insert 函数插入数据,在数据的插入上涉及到集合的唯一性这个概念,即当map中有这个关键字时, insert 操作是插入不了数据的,但是用数组方式就不同了,它可以覆盖以 前该关键字对应的值。

常用函数

(1)find(key)

返回键为key的映射的迭代器,如果未找到,返回end()的迭代器

例如:


  1. map<int,int> mp;
  2. mp.insert(pair<int,int>(1,10));
  3. if(mp.find(2)==mp.end()) cout<<"Not exist"; //输出Not exist

(2)size()

返回map中映射的对数,时间复杂度为O(1)

(3)erase(it)和erase(first,last)

erase(it) 删除迭代器it的元素,也可以用 erase(key) , 为要删除映射的键。

erase(first,last) ,删除左闭右开区间(first,last]first 为起始迭代器,last 为末尾迭代器的下一个地址。

(4)clear()

清空 map ,时间复杂度为 O(n)


  1. map<string,int> mp;
  2. mp["xyz"]=1;
  3. mp["def"]=2;
  4. mp["abc"]=3;
  5. cout<<mp.size()<<endl; //输出3
  6. map<string,int>::iterator it=mp.find("xyz");
  7. cout<<it->first<<" "<<it->second<<endl; //输出xyz 1
  8. mp.erase(it);
  9. //将这句话与find可以和合并成一句话mp.erase("xyz"),时间复杂度相同
  10. for(map<string,int>::iterator it=mp.begin();it!=mp.end();it++)
  11. cout<<it->first<<" "<<it->second<<" "; //输出abc 3 def 2
  12. it=mp.find("abc");
  13. mp.erase(it,mp.end());
  14. cout<<mp.size()<<endl; //输出0

set

简介

set翻译为集合,是一个内部自动有序切且不含重复元素的容器。set的主要作用就是**自动去重并按 升序排序 **,因此遇到不方便开数组的情况,比如元素较大或类型不是 int ,可以是一个 set 解决。 set 内部也是使用红黑树实现的。

使用时,添加 set 头文件,即 #include<set>

定义


  1. set<typename> name;

typename 可以是任意类型或容器, name 是集合名称。


  1. set<int> st; //定义int的集合st
  2. set<int> st[100]; //定义int的100个集合st[0],st[1]...st[99]

访问

set 只能通过迭代器访问。


  1. set<typename>::iterator it;

通过 *it 访问set中元素。

常用函数

(1)inset(x)

x 插入到 set 中,并自动排序去重。

如果未找到,返回 end() 的迭代器。

例如:


  1. set<int> s;
  2. s.insert(10);
  3. if(s.find(5) != s.end()) cout<<"exist"<<endl;
  4. else cout<<"Not exist"<<endl; //输出Not exist

(2)size()

返回 set 中的个数,时间复杂度为O(1)

(3)find(x)

返回set中对应值 x 的迭代器。

(4)clear

清空 set 中的元素,时间复杂度为O(n)

(5)erase(it)和erase(first,last)

erase(it) 删除迭代器it的元素,时间复杂度为 O(1),也可以用 erase(value)value 为要删除 元素的值。

erase(first,last) ,删除左闭右开区间[first,last)first为起始迭代器, last为末尾迭代器的下一个地址,时间复杂度为 O(first-last)


  1. set<int> st;
  2. for(int i=5;i<=10;i++) st.insert(i);
  3. cout<<*(st.find(2))<<endl; //输出6
  4. set<int>::iterator it=st.find(8);
  5. st.erase(it,st.end()); //删除8 9 10
  6. for(it=st.begin();it!=st.end();it++)
  7. cout<<*it<<" "; //输出5 6 7

multiset

简介

multiset set 类似,区别是multiset能够保存重复的元素。

定义


  1. multiset<typename> name;

常用函数

multiset 容器和 set 容器有相同的成员函数,但是因为 multiset可以保存重复元素,有些函数的 表现会有些不同。和set容器中的成员函数表现不同的是:

(1)insert()

总是可以成功执行。当插入单个元素时,返回的迭代器指向插入的元素。

(2)find()

会返回和参数匹配的第一个元素的迭代器,如果都不匹配,则返回容器的结束迭代器。

(3)count()

返回和参数匹配的元素的个数。

algorithm

简介

algorithm 翻译为算法,提供了大量函数

1.max(x,y),min(x,y),abs(x),swap(x,y)

max(x,y) min(x,y)返回较大值和较小值,可以是整型,也可以是浮点型。

abs(x) 返回 x的绝对值,x须是整数。如果要求浮点数绝对值,可以使用 math 头文件下的 fabs(x)

swap(x,y) 用来交换xy 的值。

2.next_permutation()

求一个序列中全排列的下一个序列。例如123的全排列为:123132213312321231 , 的 下一个排列就是 321.

基本格式: next_permutation (起始元素地址,结束元素地址的下一个地址)


  1. int a[10];
  2. a[1]=1;a[2]=2;a[3]=3;
  3. do{
  4. cout<<a[1]<<" "<<a[2]<<" "<<a[3]<<endl;
  5. }while(next_permutation(a+1,a+4)); //a[1],a[2],a[3]的排列

输出:


  1. 1 2 3
  2. 1 3 2
  3. 2 1 3
  4. 2 3 1
  5. 3 1 2
  6. 3 2 1

3.sort()

sort 是实现排序的函数。

(1)sort的基本格式:

sort( 起始元素地址,结束元素地址的下一个地址,比较函数);

比较函数缺少会默认对区间元素递增排序。


  1. bool cmp(int x,int y) //定义比较函数,string、double、char类型均可
  2. {
  3. if(x>y) return 1; //如果a>b成立,a放前面
  4. return 0; //否则放在后面
  5. }
  6. int main()
  7. {
  8. int a[6]={4,5,9,-2,5,-5};
  9. sort(a,a+4); //a[0]~a[3]从小到大排序
  10. for(int i=0;i<6;i++) cout<<a[i]<<" "; //输出 -2 4 5 9 5 -5
  11. cout<<endl;
  12. sort(a+2,a+6,cmp); //a[2]~a[5]从大到小排序
  13. for(int i=0;i<6;i++) cout<<a[i]<<" "; //输出-2 4 9 5 5 -5
  14. return 0;
  15. }

(2)结构体sort

现在对学生成绩排序,按语文从大到小排序,语文相同按数学大到小排序,数学相同,按名字字典序排序。


  1. struct stu //结构体
  2. {
  3. int chinese;
  4. int math;
  5. string name;
  6. }a[100];
  7. bool cmp(stu x,stu y) //结构体类型
  8. {
  9. if(x.chinese>y.chinese) return 1; //语文大的在前
  10. if(x.chinese<y.chinese) return 0;
  11. if(x.math>y.math) return 1; //语文相等,数学大的在前
  12. if(x.math<y.math) return 0;
  13. if(x.name>y.name) return 1; //语文数学都相等,字典序大的在前
  14. return 0;
  15. }
  16. int main()
  17. {
  18. for(int i=1;i<=5;i++)
  19. cin>>a[i].chinese>>a[i].math>>a[i].name;
  20. sort(a+1,a+6,cmp);
  21. for(int i=1;i<=5;i++)
  22. cout<<a[i].chinese<<" "<<a[i].math<<" "<<a[i].name<<endl;
  23. return 0;
  24. }

输入:


  1. 90 80 abc
  2. 90 85 xyz
  3. 92 85 ppt
  4. 92 85 bcd
  5. 100 53 hij

输出:


  1. 100 53 hij
  2. 92 85 ppt
  3. 92 85 bcd
  4. 90 85 xyz
  5. 90 80 abc

(3)容器sort

STL中的容器中,只有 vectorstring可以使用 sort() 。其他类型 map set 等,其中元素 本身就是有序的,无法使用。


  1. bool cmp(int x,int y) //结构体类型
  2. {
  3. if(x>y) return 1;
  4. return 0;
  5. }
  6. int main()
  7. {
  8. vector<int> v;
  9. for(int i=1;i<=5;i++) //输入 7 9 0 2 1
  10. {
  11. int t;
  12. cin>>t;
  13. v.push_back(t);
  14. }
  15. sort(v.begin(),v.end(),cmp);
  16. for(int i=0;i<v.size();i++)
  17. cout<<v[i]<<" "; //输出9 7 2 1 0
  18. return 0;
  19. }

4.lower_bound(first,last,val)和upper_bound(first,last,val)

lower_bound(first,last,val) 用来寻找一个有序(从小到大)数组或者容器[first,last)中,第一个 值大于或等于val的位置。如果是数组,返回该位置指针,如果是容器,返回该位置的迭代器。

upper_bound(first,last,val) 用来寻找一个有序数组或容器 [first,last)中,第一个值大于val的位置。如果是数组,返回该位置指针,如果是容器,返回该位置的迭代器。

如果数组或者容器中没有需要寻找的元素,则上面两个函数的返回值均为可以插入该位置的指针或迭代器 。

例如:


  1. int a[10]={1,2,2,3,3,3,5,5,5,5};
  2. int b[10]={5,5,5,5,3,3,3,2,2,1};
  3. int *t=lower_bound(a,a+10,2);
  4. cout<<t<<endl; //t为找到元素的地址
  5. cout<<t-a<<endl; //输出1
  6. //a为a[0]的地址,数组存储使用连续的地址,t-a即数组中第几个元素
  7. //a+2为a[2]的地址
  8. t=upper_bound(a+2,a+10,2); // t为找到元素的地址
  9. cout<<t-(a+2)<<endl; //输出3
  10. cout<<upper_bound(a,a+10,3)-a<<endl; //也可以不指针,输出6

STL常用函数的更多相关文章

  1. C++STL 常用 函数 用法

    学完c++快一年了,感觉很有遗憾,因为一直没有感觉到c++的强大之处,当时最大的感觉就是这个东西的输入输出比C语言要简单好写. 后来我发现了qt,opencv,opengl,原来,c++好玩的狠. 在 ...

  2. C++STL 常用 函数 用法(转)

    http://www.cnblogs.com/duoduo369/archive/2012/04/12/2439118.html 迭代器(iterator) 个人理解就是把所有和迭代有关的东西给抽象出 ...

  3. 【算法专题】工欲善其事必先利其器—— 常用函数和STL

    一.    常用函数 #include <stdio.h> int getchar( void );               //读取一个字符, 一般用来去掉无用字符 char *ge ...

  4. C++——STL之vector, list, deque容器对比与常用函数

    STL 三种顺序容器的特性对比: vector 可变数组,内存空间是连续的,容量不会进行缩减.支持高效随机存取,即支持[]和at()操作.尾部插入删除效率高,其他位置插删效率较低: list 双向链表 ...

  5. STL algorithm 头文件下的常用函数

    algorithm 头文件下的常用函数 1. max(), min()和abs() //max(x,y)和min(x,y)分别返回x和y中的最大值和最小值,且参数必须时两个(可以是浮点数) //返回3 ...

  6. STL之map与pair与unordered_map常用函数详解

    STL之map与pair与unordered_map常用函数详解 一.map的概述 map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称 ...

  7. STL之vector常用函数笔记

    STL之vector常用函数笔记 学会一些常用的vector就足够去刷acm的题了 ps:for(auto x:b) cout<<x<<" ";是基于范围的 ...

  8. C++ STL 常用拷贝和替换算法

    C++ STL 常用拷贝和替换算法 copy() 复制 vector<int> vecIntA; vecIntA.push_back(1); vecIntA.push_back(3); v ...

  9. C++ STL 常用查找算法

    C++ STL 常用查找算法 adjacent_find() 在iterator对标识元素范围内,查找一对相邻重复元素,找到则返回指向这对元素的第一个元素的迭代器.否则返回past-the-end. ...

  10. C++ STL 常用遍历算法

    C++ STL 常用遍历算法 STL的容器算法迭代器的设计理念 1) STL的容器通过类模板技术,实现数据类型和容器模型的分离 2) STL的迭代器技术实现了遍历容器的统一方法:也为STL的算法提供了 ...

随机推荐

  1. Visual Studio Code(vscode)下载慢 插件安装失败解决方案

    目录 一.系统环境 二.前言 三.Visual Studio Code(vscode)简介 四.解决Visual Studio Code(vscode)下载慢的问题 4.1 问题描述 4.2 解决方案 ...

  2. YShow性能测试平台搭建

    ShowSlow安装 ShowSlow是一个YSlow性能数据收集平台,用于将收集的性能数据 ShowSlow是用php实现的,所以我们需要搭建一台服务器来接收YSlow数据 我搭建的环境是:ubun ...

  3. 关于MySQL获取自增ID的几种方法

    1. Select Max(id) From Table; 通过取表字段最大值的方式来获取最近一次自增id 缺点: 这种方法在多人操作数据库的软件上不可靠, 举个例子, 你刚插入一条记录. 当你在查询 ...

  4. LVS DR模式负载均衡群集部署

    LVS DR模式负载均衡群集部署 1 LVS-DR 模式的特点 直接路由直接路由 调节器仅作为客户端的访问入口,节点服务器的响应消息是直接返回客户端的,不需要经过调节器(与NAT模式的区别)节点服务器 ...

  5. 《流畅的Python》 读书笔记 230926(第一章后半部分)

    1.2 如何使用特殊方法 特殊方法的存在是为了被 Python 解释器调用的,你自己并不需要调用它们 就是说通常你都应该用len(obj)而不是obj.__len()__,无论是系统预置的,还是你自己 ...

  6. 解密Prompt系列16. LLM对齐经验之数据越少越好?LTD & LIMA & AlpaGasus

    LLM Agent中间插个队,总结下指令微调.对齐数据相关的方案,已经凑够7篇论文可以召唤神龙啦!论文都是以优化指令样本为核心,Data-Centric的观点比较一致:指令微调也就是对齐阶段的数据质量 ...

  7. git Failed to connect to 127.0.0.1 port xxxx: Connection refused 的问题。

    问题描述在使用 git 拉取.提交代码的时候,会出现 git Failed to connect to 127.0.0.1 port xxxx: Connection refused 的问题. 原因: ...

  8. Top 6 Refactoring Patterns to Help You Score 80% in Code Quality

    Top 6 Refactoring Patterns to Help You Score 80% in Code Quality Posted by Ajitesh Kumar / In Code R ...

  9. 记一次基于 PowerShell 的 Git 自动化部署 Java 多服务实践

    前言 有这么一个自动化部署的需求,凑巧 git 还直接建立在测试服务器上,部署后可以直接在测试服务器上演示 步骤 建立 Git 仓库 与一般的 Git 部署一样,区别是需要添加 --bare 开关,这 ...

  10. ApiPost发送请求报错UT000036: Connection terminated parsing multipart data

    发送请求报错Caused by: java.io.IOException: UT000036: Connection terminated parsing multipart data 这个报错是因为 ...