STL常用函数
STL简介
STL 是 Standard Template Library 的简称,中文名称为标准模板库,从根本上讲, 就是各种 STL 容器的集合,容器可以理解为能够实现很多功能的系统的函数。常见的容器有vector
,stack
,queue
,map
,set
等。
迭代器
迭代器(iterators
)是用来访问容器中的元素,类似于指针。迭代器全部包含两个函数:
1.begin()
,返回一个容器开头的迭代器;
2.end()
,返回一个容器末尾的迭代器,但是不包括最后一个元素,而是最后一个元素的下一个地址。
定义:
containers <typename>::iterators name;
//containers为容器类型,typename为容器内的数据类型,name为迭代器名
string
简介
在 C 语言中,一般使用字符数组char str[ ]
来存放字符串,但是操作起来非常麻烦,容易出错。 在 C++中加入了string
类型用来存放字符串,使用起来更加方便。
使用时,需要添加头文件string
,即#include<string>
。
定义
string name; // name是变量名
string name2="abcde"; //可直接赋值
如果需要存放多个字符串,定义string
类型数组:
string name [N];
//name[N]可以存放N个字符串。
输入输出
如果要输入输出,只能使用cin
和cout
。使用cin
读入string
类型,就像用scanf()
读字符 数组一样,忽略开头的(制表符、换行符、空格),当再次碰到空字符就停止(并不会读取空字符)。
string s;
cin>>s;
读入时忽略了空字符,可以将其记作cin
读字符串读的是单词。当然,有时我们更希望读取的是句子。 C++ 提供了getline
函数以供使用。
getline
的原型是:getline(cin,s);
,cin
指的是读入流,一般情况下我们直接写cin
即可,s
是字符串,即我们读入的东西要存放的字符串。
string s;
getline(cin,s); // getline()读入一行的字符,会舍弃换行符
访问
(1)通过下标访问
对于string
类型的字符串进行访问,与字符数组访问一样,使用下标。如果有string
类型变量名 为s
,可直接访问对应字符s[0]
,s[1]
,s[2]
……,s[s.size()-1]
,s.size()
是用来求string
类型的长度。
(2)通过迭代器访问
string::iterator it;
定义了string
的迭代器it
,可以通过*it
访问string
中的每一个字符,在常用的STL容器 中,只有vector
和string
允许使用v.begin()+5
这种迭代器加上整数的写法,等价于访问s[5]
。同时,迭代器可以进行自加、自减操作,即it++
,++it
,it--
,--it
。
例如:
string s="abcdef";
for(string::iterator it=s.begin();it!=s.end();it++) //输出abcdef
cout<<*it<<" ";
cout<<endl;
for(string::iterator it=s.begin()+3;it!=s.end();it++) //输出def
cout<<*it<<" ";
s.end()
不是取s
的尾元素地址,而是尾元素地址的下一个地址,不存储任何元素,不支持it<end()
的写法。
运算
①string
类型可以直接进行加法运算。但是加法是将两个字符串拼接起来。
例如:
string s1="abc",s2="efgh";
cout<<s1+s2; //输出abcefgh
② string 类型可以互相进行复制。
例如:
string s3;
s3=s2;
cout<<s3; //输出efgh
③ string 类型可以直接进行关系运算。直接比较大小,按照字典序进行比较。
if(s1>s2) cout<<1;
else cout<<0; //最后结果为0,"efgh"字典序大于"abc"
//判断是否相等。 s
tring s1="abc",s2="abc";
if(s1==s2) cout<<1; //会输出1
常用函数
① size()和length()
这两个函数都是返回string
类型的长度(字符个数)。时间复杂度 O(1)。
② clear()和empty()
clear()
用来清空string
中的所有元素,时间复杂度为O(1) 。
empty()
用来判断string
是否为空,是返回true
,否则返回false
。
例如:
string s="abcde";
cout<<s.size (); //输出5
s.clear();
cout<<s.length(); //输出0
if(s.empty()) cout<<1;
else cout<<0; //输出1
③ insert(pos,s2)
在s
下标为pos
的元素前插入string
类型s2
。 例如:
string s="abcde",s2="opq";
s.insert(3,s2);
cout<<s; //输出abcopqde
④ erase(pos,len)
删除s
中下标为pos
开始的len
个字符 。
例如:
string s="abcdefgh";
s.erase(3,3);
cout<<s; //输出abcgh
⑤ find(s2)
当s2
是s
子串时,返回在s
中第一次出现的位置,否则,返回string::npos
。
例如:
string s="abcdefabcde",s2="cde";
if(s.find(s2)!=string::npos) cout<<s.find(s2); //输出2
//s.find(s2,pos),是在 s 中以 pos 位置起查找 s2 第一次出现的位置,返回值s.find(s2)相同
⑥ replace(pos,len,s2)
删除s
中下标为pos
开始的len
个字符,并在下标为pos
处插入s2
。
例如:
string s1="asfgg",s2="ad";
s1.replace(1,1,s2);
cout<<s1<<endl; //输出aadfgg
vector
简介
vector
为变成数组,即长度可以根据需要进行改变的数组。在信息学竞赛中,有些题目需要定义很大 的数组,这样会出现"超出内存限制"的错误,使用vector
简洁方便,还可以节省空间。
使用时,需要添加头文件vector
,即#include<vector>
。
定义
vector<typename> name;
以上定义相当于定义了一个一维数组name[size]
,只是size
不确定,大小可以根据需要而变化。 其中 tyepename
为基本类型,如int
、double
、char
、结构体等,也可以是STL的容器,如string
、queue
,vector
等。
例如:
vector<int> a;
vector<double> score;
vector<node> stu; //node为已经定义了得结构体
但是,如果typename
也是一个 STL 容器,那么定义时,需要在两个 ">"之间加上一个空格,因为">>"会被当作右移运算,从而导致编译出错,例如:
vector<int> a[100]; //定义一个一维长度固定为100,另一维不确定的二维数组a[100][size]
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)
在vecto
r 迭代器 it 处插入一个元素 x , x 后的元素后移,时间复杂度为**O(n) .
(6)erase(it)、erase(first,last)
删除vector
中的元素元素。erase(it)
,删除迭代器it
处的元素; erase(first,last) ,删除左闭右开区间内的所以元素。
例如:
vector<int> v;
for(int i=1;i<=5;i++) v.push_back(i); //数组元素为1 2 3 4 5
for(int i=0;i<v.size();i++) cout<<v[i]<<" "; //输出1 2 3 4 5
cout<<endl;
v.pop_back();
for(int i=0;i<v.size();i++) cout<<v[i]<<" "; //输出1 2 3 4
cout<<endl;
v.insert(v.begin()+2,10); //将10插入到v[2]处
for(int i=0;i<v.size();i++) cout<<v[i]<<" "; //输出1 2 10 3 4
cout<<endl;
v.erase(v.begin()+1,v.begin()+3); //删除v[1],v[2],
for(int i=0;i<v.size();i++) cout<<v[i]<<" "; //输出1 3 4
cout<<endl;
v.clear();
cout<<v.size(); //输出0
访问
访问vector
中的元素一般有两种方式。
(1)通过下标进行访问,对于容器vector
v
,可以使用v[i]
来访问第i
个元素。
(2)通过迭代器访问
定义:
vector<int>::iterator it;
定义一个迭代器it
,通过*it
访问int
类型的vector
中的元素。
在常用的容器中,只有vector
和string
允许使用v.begin()+5
这种迭代器加上整数的写法。
vector<int> v;
for(int i=1;i<=5;i++) v.push_back(i); //数组元素为1 2 3 4 5
vector<int>::iterator it=v.begin();
for(int i=0;i<v.size();i++)
cout<<(it+i)<<" "; //输出1 2 3 4 5
同时,迭代器可以进行自加、自减操作,即it++
,++it
,it--
,--it
。
vector<int> v;
for(int i=1;i<=5;i++) v.push_back(i); //数组元素为1 2 3 4 5
for(vector<int>::iterator it=v.begin();it!=v.end();it++)
cout<<*it<<" "; //输出1 2 3 4 5
stack
简介
stack
翻译为栈,实现先进后出的容器。
使用时,需要添加头文件stack
,即#include<stack>
。
定义
stack<typename> name;
例如:
stack<int> s; //定义一个int类型的栈s
常用函数
(1)push(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)。
例如:
stack<int> s;
for(int i=1;i<=5;i++) s.push(i); //栈元素为1 2 3 4 5
s.pop(); //删除栈顶元素5
cout<<s.top()<<endl; //输出4
cout<<s.size()<<endl; //输出4
while(!s.empty())
{
cout<<s.top(); //输出 4 3 2 1
s.pop();
}
queue
简介
queue
翻译为队列,是一个"先进先出"的容器。 使用时,需要添加头文件queue
,即#include <queue>
。
定义
queue <typename> name; // name是变量名
例如:
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>
。
定义
priority_queue <typename> name;
例如:
priority_queue <int> q; //定义一个int类型,名为q的优先队列:
这样定义的是一个大根堆,它的原型其实是:
priority_queue <int,vector<int>,less<int> > q;
尖括号中多了两个参数,vector<int>
,表示的是承载底层数据结构——堆的容器,类型与第一个参 数一致; less ,是对第一个参数的比较类,表示数字越大优先级越大(大根堆),而如果用 greater ,则表示数字越小优先级越大。
因此,定义大根堆有两种方法,这两种方法是等价的:
priority_queue <int> q;
priority_queue <int,vector<int>,less<int> > q;
定义小根堆:
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()
判断是否为空,否则可能因为队空出现错误。
例如:
priority_queue <int,vector<int>,greater<int> > q; //定义小根堆
q.push(4);
q.push(6);
q.push(3);
q.push(9);
if(!q.empty()) cout<<q.top(); //输出3
q.pop();
if(!q.empty()) cout<<q.top(); //输出4
结构体
如果优先队列的元素是结构体。
现在读入若干学生的语文、数学成绩和姓名,按照按语文从大到小排序,语文相同按数学大到小排序, 数学相同,按名字字典序排序。
也可以使用pair
,更方便。
例如:
struct stu
{
int chinese;
int math;
string name;
bool operator<(const stu &x) const{
if(chinese<x.chinese) return 1; //语文大的在前,和sort相反
if(chinese>x.chinese) return 0;
if(math<x.math) return 1; //语文相等,数学大的在前
if(math>x.math) return 0;
if(name>x.name) return 1; //语文数学都相等,字典序大的在前
return 0;
}
};
priority_queue<stu> q;
int main()
{
stu a;
a.chinese=90;a.math=80;a.name="abc";
q.push(a); //放入
a.chinese=90;a.math=85;a.name="xyz";
q.push(a);
a.chinese=90;a.math=85;a.name="yyy";
q.push(a);
a.chinese=92;a.math=85;a.name="bcd";
q.push(a);
a=q.top();
cout<<a.chinese<<" "<<a.math<<" "<<a.name<<endl; //输出 92 85 bcd
q.pop(); //删除第一个
a=q.top();
cout<<a.chinese<<" "<<a.math<<" "<<a.name<<endl; //输出 90 85 xyz
return 0;
}
pair
pair
是二元结构体,将两个元素捆绑在一起,相当于:
struct pair
{
typename1 first;
typename2 second;
}
使用时,需要添加头文件#include<utility>
。
定义
pair
有两个参数,可以是任意基本类型或容器。
pair <typename1,typename2> name;
初始化
pair
使用first
和second
访问第一,第二个元素。
pair
有三种初始化的方式,如下:
pair<string,int> p("abc",1); //初始化1
cout<<p.first<<" "<<p.second<<endl; //输出abc 1
p.first="bcd"; //初始化2
p.second=5;
cout<<p.first<<" "<<p.second<<endl; //输出bcd 5
p=make_pair("xyz",9); //初始化3
cout<<p.first<<" "<<p.second<<endl; //输出xyz 9
如果有三个元素,也可以用pair
实现:
pair<int,pair<int,int> > p[100]; //> >中间有空格,否则会被当作位移运算
p[1].first=1;
p[1].second.first=5;
p[1].second.second=2;
cout<<p[1].first<<" "<<p[1].second.second; //输出1 2
pair
可以直接做比较。比较规则是先以first
的大小作为标准,只有当first
相等时才去判断second
的大小。
例如:
pair<int,int> p1(5,10);
pair<int,int> p2(5,15);
pair<int,int> p3(10,5);
if(p1<p3) cout<<"p1<p3"<<endl; //输出p1<p3
if(p1<p2) cout<<"p1<p2"<<endl; //输出p1<p2
if(p1<=p3) cout<<"p1<=p3"<<endl; //输出p1<=p3make<int,int> p1(5,10);
map
简介
map
翻译为映射。其实,数组就是一种映射。int a[100]
定义了一个int
到int
的映射,a[5]=25
,把5
映射到25
。数组总是将int
类型映射到其他类型。如果要将string
类型映射到int
类型,数组就很不方便,此时可以使用map
,map
可以将任意基本类型(包括STL容器)映射 到任意基本类型(包括STL类型)。
map
常用情形:
1)建立字符(串)与整数之间的映射
2)判断大整数(几千位)或者其他类型数据是否存在,可以将map
当布尔数组使用,实现类似哈希表的功 能。
3)字符串与字符串的映射。 使用时,需要添加头文件map
,即#include<map>
。
定义
map<typename1,typename2> name;
typename1
是映射前的类型(键 ),typename2
是映射后的类型(value值 ),name
为映射名称。
普通in
t 数组a
就是:map<int,int> a;
字符串映射到整型,必须使用string
,不能使用char
:map<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的键值对来插入。
map<string,int> mp;
mp.insert(pair<string,int>("xyz",1));
mp.insert(pair<string,int>("def",2));
mp.insert(pair<string,int>("abc",3));
for(map<string,int>::iterator it=mp.begin();it!=mp.end();it++)
cout<<it->first<<" "<<it->second<<" "; //输出abc 3 def 2 xyz 1
可以看出,map
建立映射后,会自动实现按键从小到大排序,这是因为map
内部使用红黑树实现的 (set
也是如此)。
(2)用数组进行插入
map<string,int> mp;
mp["abc"]=1;
mp["def"]=2;
mp["xyz"]=3;
for(map<string,int>::iterator it=mp.begin();it!=mp.end();it++)
cout<<it->first<<" "<<it->second<<" "; //输出abc 1 def 2 xyz 3
但是它们是有区别的,用insert
函数插入数据,在数据的插入上涉及到集合的唯一性这个概念,即当map
中有这个关键字时,insert
操作是插入不了数据的,但是用数组方式就不同了,它可以覆盖以 前该关键字对应的值。
常用函数
(1)find(key)
返回键为key的映射的迭代器,如果未找到,返回end()
的迭代器
例如:
map<int,int> mp;
mp.insert(pair<int,int>(1,10));
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)。
map<string,int> mp;
mp["xyz"]=1;
mp["def"]=2;
mp["abc"]=3;
cout<<mp.size()<<endl; //输出3
map<string,int>::iterator it=mp.find("xyz");
cout<<it->first<<" "<<it->second<<endl; //输出xyz 1
mp.erase(it);
//将这句话与find可以和合并成一句话mp.erase("xyz"),时间复杂度相同
for(map<string,int>::iterator it=mp.begin();it!=mp.end();it++)
cout<<it->first<<" "<<it->second<<" "; //输出abc 3 def 2
it=mp.find("abc");
mp.erase(it,mp.end());
cout<<mp.size()<<endl; //输出0
set
简介
set
翻译为集合,是一个内部自动有序切且不含重复元素的容器。set
的主要作用就是**自动去重并按 升序排序 **,因此遇到不方便开数组的情况,比如元素较大或类型不是int
,可以是一个set
解决。set
内部也是使用红黑树实现的。
使用时,添加set
头文件,即#include<set>
。
定义
set<typename> name;
typenam
e 可以是任意类型或容器,name
是集合名称。
set<int> st; //定义int的集合st
set<int> st[100]; //定义int的100个集合st[0],st[1]...st[99]
访问
set
只能通过迭代器访问。
set<typename>::iterator it;
通过*it
访问set
中元素。
常用函数
(1)inset(x)
将x
插入到set
中,并自动排序去重。
如果未找到,返回end()
的迭代器。
例如:
set<int> s;
s.insert(10);
if(s.find(5) != s.end()) cout<<"exist"<<endl;
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)。
set<int> st;
for(int i=5;i<=10;i++) st.insert(i);
cout<<(st.find(2))<<endl; //输出6
set<int>::iterator it=st.find(8);
st.erase(it,st.end()); //删除8 9 10
for(it=st.begin();it!=st.end();it++)
cout<<*it<<" "; //输出5 6 7
multiset
简介
multiset
与set
类似,区别是multiset
能够保存重复的元素。
定义
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)
用来交换x
和y
的值。
2.next_permutation()
求一个序列中全排列的下一个序列。例如123的全排列为:123 ,132 ,213 ,312 ,321 ,231 , 的 下一个排列就是 321.
基本格式:next_permutation
(起始元素地址,结束元素地址的下一个地址)
int a[10];
a[1]=1;a[2]=2;a[3]=3;
do{
cout<<a[1]<<" "<<a[2]<<" "<<a[3]<<endl;
}while(next_permutation(a+1,a+4)); //a[1],a[2],a[3]的排列
输出:
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
3.sort()
sort
是实现排序的函数。
(1)sort的基本格式:
sort( 起始元素地址,结束元素地址的下一个地址,比较函数);
比较函数缺少会默认对区间元素递增排序。
bool cmp(int x,int y) //定义比较函数,string、double、char类型均可
{
if(x>y) return 1; //如果a>b成立,a放前面
return 0; //否则放在后面
}
int main()
{
int a[6]={4,5,9,-2,5,-5};
sort(a,a+4); //a[0]~a[3]从小到大排序
for(int i=0;i<6;i++) cout<<a[i]<<" "; //输出 -2 4 5 9 5 -5
cout<<endl;
sort(a+2,a+6,cmp); //a[2]~a[5]从大到小排序
for(int i=0;i<6;i++) cout<<a[i]<<" "; //输出-2 4 9 5 5 -5
return 0;
}
(2)结构体sort
现在对学生成绩排序,按语文从大到小排序,语文相同按数学大到小排序,数学相同,按名字字典序排序。
struct stu //结构体
{
int chinese;
int math;
string name;
}a[100];
bool cmp(stu x,stu y) //结构体类型
{
if(x.chinese>y.chinese) return 1; //语文大的在前
if(x.chinese<y.chinese) return 0;
if(x.math>y.math) return 1; //语文相等,数学大的在前
if(x.math<y.math) return 0;
if(x.name>y.name) return 1; //语文数学都相等,字典序大的在前
return 0;
}
int main()
{
for(int i=1;i<=5;i++)
cin>>a[i].chinese>>a[i].math>>a[i].name;
sort(a+1,a+6,cmp);
for(int i=1;i<=5;i++)
cout<<a[i].chinese<<" "<<a[i].math<<" "<<a[i].name<<endl;
return 0;
}
输入:
90 80 abc
90 85 xyz
92 85 ppt
92 85 bcd
100 53 hij
输出:
100 53 hij
92 85 ppt
92 85 bcd
90 85 xyz
90 80 abc
(3)容器sort
STL中的容器中,只有vector
、string
可以使用sort()
。其他类型map
、set
等,其中元素 本身就是有序的,无法使用。
bool cmp(int x,int y) //结构体类型
{
if(x>y) return 1;
return 0;
}
int main()
{
vector<int> v;
for(int i=1;i<=5;i++) //输入 7 9 0 2 1
{
int t;
cin>>t;
v.push_back(t);
}
sort(v.begin(),v.end(),cmp);
for(int i=0;i<v.size();i++)
cout<<v[i]<<" "; //输出9 7 2 1 0
return 0;
}
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的位置。如果是数组,返回该位置指针,如果是容器,返回该位置的迭代器。
如果数组或者容器中没有需要寻找的元素,则上面两个函数的返回值均为可以插入该位置的指针或迭代器 。
例如:
int a[10]={1,2,2,3,3,3,5,5,5,5};
int b[10]={5,5,5,5,3,3,3,2,2,1};
int *t=lower_bound(a,a+10,2);
cout<<t<<endl; //t为找到元素的地址
cout<<t-a<<endl; //输出1
//a为a[0]的地址,数组存储使用连续的地址,t-a即数组中第几个元素
//a+2为a[2]的地址
t=upper_bound(a+2,a+10,2); // t为找到元素的地址
cout<<t-(a+2)<<endl; //输出3
cout<<upper_bound(a,a+10,3)-a<<endl; //也可以不指针,输出6