C++标准库模板 Standard Template Library(STL)
vector常用方法
vector翻译为向量,或者边长数组,即长度根据需要而自动改变的数组。
1.创建vector的构造方法
#include<iostream>
#include<vector>
#include<cstdio>
using namespace std;
int main()
{
//创建二维向量
vector<int> v;
vector<vector<int> > v2;
for(int i=0;i<10;i++)
v.push_back(i);
for(int i=0;i<10;i++)
v2.push_back(v);
//输出结果
for(int i=0;i<v2.size();i++){
for(int j=0;j<v2[i].size();j++)
cout<<v2[i][j]<<' ';
cout<<endl;
}
getchar();getchar();
return 0;
}
运行结果
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
2.常用的函数(这里只列出几种常用的函数)
函数名称 | 作用 | 时间复杂度 |
---|---|---|
push_back(x) | 在vector后面添加一个元素x | O(1) |
pop_back() | 删除vector的尾元素 | O(1) |
size() | 用来获取vector中元素的个数 | O(1) |
clear() | 用来清空vector中的所有元素 | O(N) |
insert(it,x) | 用来向vector的任意迭代器 it 处插入一个元素x | O(N) |
erase() | 1.删除单个元素 2.删除一个区间内的所有元素 | O(N) |
1.erase(it); //删除迭代器it处的元素
2.erase(first,last); //删除区间 [first,last) 内的所有元素
3.vector容器内元素访问
1)通过下标访问
2)通过迭代器访问
vector<int>::iterator it; //定义一个迭代器
for(it=v.begin();it!=v.end();it++){
cout<<*it<<' ';
}
//v.begin()是vector对象v的首地址,v.end()是尾元素地址的下一个地址
//注意上面it!=v.end();不能写成it<v.end();
set常见用法
set是集合,是一个内部自动有序且不含重复元素的容器。
1.set的定义
set<typename> name;
//typename可以是任何基本类型、结构体类型、或者是STL标准容器
//set数组定义
set<int> a[100];
2.set常用函数
函数名 | 函数功能 | 时间复杂度 |
---|---|---|
insert(x) | 将x插入set容器中 | O(logN) |
find(value) | 返回set中对应值为value的迭代器,如果没有该值,返回set.end() | O(logN) |
erase() | 1.删除单个元素 2.删除一个区间内的所有元素 | |
size() | 用来得到set中元素的个数 | O(1) |
clear() | 用于清空set中所有的元素 | O(N) |
earse()函数用法
set<int> st;
一、删除单个元素
1).st.erase(it); it为所需要删除元素的迭代器。时间复杂度为O(1)。
可以结合find()函数来使用。(用find()函数获得要删除元素的迭代器,用erase()函数删除。)
2).st.erase(value); value为所需要删除元素的值。时间复杂度为O(N).
二、删除一个区间内的所有元素
st.erase(first,last); 删除区间[first,last)中的所有元素。时间复杂度为O(last-first)。
//find()函数的使用
#include<iostream>
#include<set>
#include<cstdio>
using namespace std;
int main()
{
set<int> st;
set<int>::iterator it;
for(int i=0;i<15;i++){//在集合中插入0~14
st.insert(i);
}
cout<<"输入值n,并判断集合st中是否存在n"<<endl;
int n;
while(scanf("%d",&n)&&n>=0){
it=st.find(n);
if(it!=st.end())
cout<<"集合st中存在值"<<n<<endl;
else
cout<<"集合st中不存在值"<<n<<endl;
}
getchar();getchar();
return 0;
}
运行结果:
输入值n,并判断集合st中是否存在n
10
集合st中存在值10
14
集合st中存在值14
15
集合st中不存在值15
20
集合st中不存在值20
3.set容器内元素的访问
set只能通过迭代器访问
set<typename>::iterator it; //定义一个迭代器
//除vector和string之外的STL容器都不支持*(it+i)的访问方式,只能按如下方式枚举
for(it=st.begin();it!=st.end();it++)
cout<<*it<<endl;
string常见用法
1.string定义
string str;
2.string中内容访问
1)通过下标访问
2)通过迭代器访问
#include<iostream>
#include<string>
#include<cstdio>
using namespace std;
int main()
{
string str="hello world"; //定义string
printf("通过下标访问:");
for(int i=0;i<str.length();i++){
printf("%c",str[i]);
}
printf("\n通过迭代器访问:");
string::iterator it; //定义迭代器,不需要参数
for(it=str.begin();it!=str.end();it++){
cout<<*it;
}
getchar();getchar();
return 0;
}
*如果要读入或输出整个字符串,只能使用cin和cout
如果使用printf输出string字符串,可以先将string转化成字符数组,然后再输出,用到的函数为c_str()。
string str="hello world"; //定义string
printf("%s\n",str.c_str());
3.string常用函数
函数 | 功能 | 时间复杂度 |
---|---|---|
+、+= | string字符串可以使用+、+=进行拼接 | |
比较符号 | 可以使用==,!=,>,<,>=,<=等符号按照字典序进行比较 | |
length()和size() | 都返回字符串长度 | O(1) |
insert() | 1.insert(pos,string),在位置pos(pos是整数)处插入字符串string;2.insert(it,it2,it3),it为待插入位置的迭代器,it2,it3为待插入字符串的首尾迭代器 | O(N) |
erase() | 1.删除单个元素,str.erase(it),it为迭代器;2.删除一个区间内的所有元素str.erase(first,last);其中first、last为迭代器;3.str.erase(pos,length);pos为起始位置,length是要删除的长度 | O(N) |
clear() | 清空string | O(1) |
substr() | substr(pos,len)返回从pos位置开始,长度为len的子串 | O(len) |
string::npos | 是一个常数,值为-1,为find()函数失配时的返回值 | |
find() | str.find(str2),当str2为str子串时,返回值为第一次出现的位置;否则返回string::npos,(n,m分别是str和str2的长度) | O(nm) |
replace() | str.replace(pos,len,str2)把从pos号位开始、长度为len的子串替换为str2 | O(str.length) |
map常见用法
map为映射,可以将任何基本类型映射到任何基本类型。map会根据键值从小到大自动排序。(map、set内部都是用红黑树实现的)
1.定义map
#include<map>
using namespace std;
map<typename1,typename2> mp; //typename1为键(key)的类型,typename2为值(value)的类型
2.map容器内元素的访问
1)根据下标访问
这种访问方式类似于数组,建立映射是也可以直接根据下标进行赋值。map的键值是唯一的,这一位置对同一键进行赋值后,新的值会覆盖旧的值。
#include<iostream>
#include<map>
#include<cstdio>
#include<string>
using namespace std;
int main()
{
map<char,int> mp; //定义一个char到int的映射
//建立映射时,可以用类似数组赋值的方式
mp['a']=1;
mp['b']=2;
mp['c']=3;
//用下标的方式访问容器内元素
cout<<mp['a']<<endl;
getchar();getchar();
return 0;
}
2)使用迭代器访问
//定义迭代器
map<typename1,typename2>::iterator it;
//it 可以同时访问键和值
//it->first、it->second分别用来访问键和值
#include<iostream>
#include<map>
#include<cstdio>
using namespace std;
int main()
{
map<char,int> mp; //定义一个char到int的映射
for(char ch='f';ch>='a';ch--){
mp[ch]=int(ch-'a');
}
//使用迭代器访问
map<char,int>::iterator it;
for(it=mp.begin();it!=mp.end();it++){
cout<<it->first<<' '<<it->second<<endl;
}
getchar();getchar();
return 0;
}
运行结果(自动有序)
3.map常用函数
函数名 | 功能 | 时间复杂度 |
---|---|---|
find() | find(key)返回键为key的映射的迭代器,如果找不到返回迭代器map.end(); | O(logN) |
erase() | 1.删除单个元素 2.删除一个区间内的所有元素 | |
size() | 获取map中映射的对数 | O(1) |
clear() | 清空map中所有的元素 | O(N) |
mp.erase(it); //it为所要删除元素的迭代器 ,O(1)
mp.erase(key);//key为所要删除元素的键 ,O(logN)
mp.erase(first,last);//first、last为迭代器,删除区间[first,last),O(last-first)
向map容器中插入新的键值对insert()函数
处理上面例子中所使用的用数组的方式插入数据,还可以用insert()函数向map中添加数据
1)用insert函数插入pair数据
2)用insert函数插入value_type数据
#include<iostream>
#include<map>
#include<cstdio>
#include<string>
using namespace std;
int main()
{
map<string,int> mp;
//第一种方法,数组方式插入新数据
mp["today"]=30;
//第二种方式,用insert函数插入pair数据
mp.insert(pair<string,int>("tomorrow",31));
//第三种方式,用insert函数插入value_type数据
mp.insert(map<string,int>::value_type("yesterday",29));
//遍历map中内容
map<string,int>::iterator it;
for(it=mp.begin();it!=mp.end();it++){
cout<<it->first<<"\t"<<it->second<<endl;
}
getchar();getchar();
return 0;
}
/*
以上三种用法,虽然都可以实现数据的插入,但是它们是有区别的,当然了第二种和第三种在效果上是完成一样的,
用insert函数插入数据,在数据的插入上涉及到集合的唯一性这个概念,即当map中有这个关键字时,insert操作
是插入数据不了的,但是用数组方式就不同了,它可以覆盖以前该关键字对应的值
*/
4.map常见用途
1)建立字符串与整数之间的映射,字符串只能用string而不能用char数组
2)判断大整数或者其他类型数据是否存在,把map当bool数组使用
3)字符串和字符串的映射
queue常见用法
queue队列,先进先出的容器
1.定义
#include<queue>
using namespace std;
queue<typename> q;
2.queue容器内元素的访问
只能够访问队首或者队尾元素,分别用front()和back()来访问
3.queue常用函数
函数名 | 作用 | 时间复杂度 |
---|---|---|
push() | push(x)将元素x入队列 | O(1) |
front() | 获得队首元素 | O(1) |
back() | 获得队尾元素 | O(1) |
pop() | 队首元素出队列 | O(1) |
empty() | 判断对列是否为空 | O(1) |
size() | 获得queue中元素的个数 | O(1) |
4.queue用途
实现广度优先搜素时,不必自己手写一个队列,而用queue代替
在使用front()和pop()前,必须用empty()判断队列是否为空
priority_queue常见用法
priority_queue优先队列,底层用堆来实现,队首元素是队列中优先级最高的那个。每次向优先队列中增加一个元素或者取出队首元素后,优先队列会岁时进行调整,使队首元素总是优先级最大的那个。
1.定义
#include<queue>
using namespace std;
priority_queue<typename> q;
2.priority_queue元素的访问
优先队列没有front()函数和back()函数,只能通过top()函数访问队首元素(堆顶)。
3.priority_queue常用函数
函数名 | 功能 | 时间复杂度 |
---|---|---|
push() | push(x)将元素入队列 | O(logN) |
top() | 获得队首元素 | O(1) |
pop() | 令堆顶元素出队列 | O(logN) |
empty() | 判断优先队列是否为空 | O(1) |
size() | 返回优先队列内元素的个数 | O(1) |
使用top()前,必须用empty()函数判断优先队列是否为空,否则可能会出错
4.priority_queue元素优先级设置
1)基本数据类型
int、double、char等类型,数值越大优先级越高。
定义优先队列的两种方式:
priority_queue<int> q;
priority_queue<int,vector<int>,less<int> > q; //最后两个>中间有个空格,否则编译器版本过低会认为是移位运算符
第二种定义方式多了两个参数,参数vector<int>
表示用来承载底层数据结构堆的容器,如果第一个参数是double,则第二个参数同样要改成vector<double>
以此类推。第三个参数less<int>'
表示数字越大优先级越高,而greater<int>
表示数字越小优先级越高。
2)结构体类型的优先级设置
设置结构体变量的优先级需要重载小于号"<"。重载是指对已有的运算符进行重新定义,也就是说,可以改变小于号的功能。(只能重载小于号,重载大于号会导致错误)
(1)在结构体内定义优先级,使用友元函数(关键字:friend)重载小于号
以这种方式定义优先级后,在定义一个优先队列时用第一种方式
struct node{
int x;
int y;
friend bool operator < (node a,node b){
return a.x > b.x; //这里选择优先级比较的内容(x或y)和优先级与数值大小的关系(大于号或小于号)
}
};
#include<iostream>
#include<queue>
#include<string>
#include<cstdio>
using namespace std;
typedef struct node{ //定义一个结构体
string name;
int score;
friend bool operator < (node a,node b){ //重载小于号
return a.score < b.score; //这里是小于号,说明还是以大的值优先级高
//return a.score > b.score; //这里是大于号,小于号重载后变成大于号的功能,以小的值优先级高
}
}Stu;
int main()
{
priority_queue<Stu> q;
Stu st[6];
string names[6]={"小明","小强","小红","小花","小丽","小亮"};
int scores[6]={80,70,90,85,60,95};
for(int i=0;i<6;i++){
st[i].name=names[i];
st[i].score=scores[i];
q.push(st[i]); //放入优先队列
}
//遍历输出
while (!q.empty())
{
cout<<q.top().name<<'\t'<<q.top().score<<endl;
q.pop(); //堆顶元素出队列
}
getchar();getchar();
return 0;
}
运行结果:
如果将结构体中友元函数中的return语句替换下面注释掉的那句,运行结果如下:
(2)在原结构体外部定义优先级,这里有以下几处不同。
第一,函数用一个单独的结构体(struct)封装起来
第二,没有关键字friend
第三,把operator后面的小于号改成小括号
第四,在定义优先队列时,使用第二种定义方式需要写三个参数,第三个参数为自己定义的优先级cmp
struct node{
int x;
int y;
};
//定义优先级
struct cmp{
bool operator () (node a,node b){
return a.x < b.x; //……
}
};
#include<iostream>
#include<queue>
#include<string>
#include<cstdio>
using namespace std;
typedef struct node{
string name;
int score;
}Stu;
struct cmp{ //成绩越高优先级越高
bool operator () (Stu a,Stu b){
return a.score < b.score;
}
};
struct cmp2{//成绩越低优先级越高
bool operator () (Stu a,Stu b){
return a.score > b.score;
}
};
int main()
{
priority_queue<Stu,vector<Stu>,cmp> q;
priority_queue<Stu,vector<Stu>,cmp2> q2;
Stu st[6];
string names[6]={"小明","小强","小红","小花","小丽","小亮"};
int scores[6]={80,70,90,85,60,95};
for(int i=0;i<6;i++){
st[i].name=names[i];
st[i].score=scores[i];
q.push(st[i]); //放入优先队列
q2.push(st[i]);
}
//遍历输出
cout<<"成绩越高优先级越高"<<endl;
while (!q.empty())
{
cout<<q.top().name<<'\t'<<q.top().score<<endl;
q.pop(); //堆顶元素出队列
}
cout<<"成绩越低优先级越高"<<endl;
while (!q2.empty())
{
cout<<q2.top().name<<'\t'<<q2.top().score<<endl;
q2.pop(); //堆顶元素出队列
}
getchar();getchar();
return 0;
}
运行结果:
stack常见用法
stack,栈,先进后出的容器
1.stack定义
#include<stack>
using namespace std;
stack<typename> st;
2.stack容器内元素访问
由于stack是一种先进后出的容器,只能通过top()访问栈顶元素
3.stack常用函数
函数名 | 功能 | 时间复杂度 |
---|---|---|
push() | push(x)将想入栈 | O(1) |
top() | 获取栈顶元素 | O(1) |
pop() | 弹出栈顶元素 | O(1) |
empty() | 判断栈是否为空 | O(1) |
size() | 获得stack中元素个数 | O(1) |
pair常见用法
pair可以看做内部有两个元素的结构体,这两个元素的类型是可以指定的。
struct pair{
typename1 first;
typename2 second;
};
1.pair定义
#include<utility>
using namespace std;
pair<typename1,typename2> p;
//例如
pair<string,int> p;
pair<string,int> p2("hello",100); //定义pair的同时进行初始化
头文件map中包含头文件utility,可以用map代替
如果想在代码中临时构建一个pair,有两种方式
//第一种
pair<string,int>("hello",100); //临时变量,没有变量名
//第二种
make_pair("hello",100); //使用自带的make_pair函数
2.pair元素访问
pair只有两个元素:first、second ,访问方式和结构体一样
#include<iostream>
#include<utility>
#include<string>
#include<cstdio>
using namespace std;
int main()
{
pair<string,int> p1,p2,p3;
p1.first="hello";
p1.second=100;
p2=pair<string,int>("nihao",200); //用临时变量赋值
p3=make_pair("good",300);
cout<<p1.first<<'\t'<<p1.second<<endl;
cout<<p2.first<<'\t'<<p2.second<<endl;
cout<<p3.first<<'\t'<<p3.second<<endl;
getchar();getchar();
return 0;
}
运行结果:
3.pair常用函数
两个pair类型数据可以直接使用==、!=、<、<=、>、>=进行比较。
比较规则:先比较first的大小,只有当first相等时才比较second的大小
4.pair常见用途
1)用来代替二元结构体
2)用作map的键值对进行插入
各种容器常用函数汇总
只是常用的几个,并不是全部
1vector
函数名称 | 作用 | 时间复杂度 |
---|---|---|
push_back(x) | 在vector后面添加一个元素x | O(1) |
pop_back() | 删除vector的尾元素 | O(1) |
size() | 用来获取vector中元素的个数 | O(1) |
clear() | 用来清空vector中的所有元素 | O(N) |
insert(it,x) | 用来向vector的任意迭代器 it 处插入一个元素x | O(N) |
erase() | 1.删除单个元素 2.删除一个区间内的所有元素 | O(N) |
2.set
函数名 | 函数功能 | 时间复杂度 |
---|---|---|
insert(x) | 将x插入set容器中 | O(logN) |
find(value) | 返回set中对应值为value的迭代器,如果没有该值,返回set.end() | O(logN) |
erase() | 1.删除单个元素 2.删除一个区间内的所有元素 | |
size() | 用来得到set中元素的个数 | O(1) |
clear() | 用于清空set中所有的元素 | O(N) |
3.string
函数 | 功能 | 时间复杂度 |
---|---|---|
+、+= | string字符串可以使用+、+=进行拼接 | |
比较符号 | 可以使用==,!=,>,<,>=,<=等符号按照字典序进行比较 | |
length()和size() | 都返回字符串长度 | O(1) |
insert() | 1.insert(pos,string),在位置pos(pos是整数)处插入字符串string;2.insert(it,it2,it3),it为待插入位置的迭代器,it2,it3为待插入字符串的首尾迭代器 | O(N) |
erase() | 1.删除单个元素,str.erase(it),it为迭代器;2.删除一个区间内的所有元素str.erase(first,last);其中first、last为迭代器;3.str.erase(pos,length);pos为起始位置,length是要删除的长度 | O(N) |
clear() | 清空string | O(1) |
substr() | substr(pos,len)返回从pos位置开始,长度为len的子串 | O(len) |
string::npos | 是一个常数,值为-1,为find()函数失配时的返回值 | |
find() | str.find(str2),当str2为str子串时,返回值为第一次出现的位置;否则返回string::npos,(n,m分别是str和str2的长度) | O(nm) |
replace() | str.replace(pos,len,str2)把从pos号位开始、长度为len的子串替换为str2 | O(str.length) |
4.map
函数名 | 功能 | 时间复杂度 |
---|---|---|
find() | find(key)返回键为key的映射的迭代器,如果找不到返回迭代器map.end(); | O(logN) |
erase() | 1.删除单个元素 2.删除一个区间内的所有元素 | |
size() | 获取map中映射的对数 | O(1) |
clear() | 清空map中所有的元素 | O(N) |
5.queue
函数名 | 作用 | 时间复杂度 |
---|---|---|
push() | push(x)将元素x入队列 | O(1) |
front() | 获得队首元素 | O(1) |
back() | 获得队尾元素 | O(1) |
pop() | 队首元素出队列 | O(1) |
empty() | 判断对列是否为空 | O(1) |
size() | 获得queue中元素的个数 | O(1) |
6.priority_queue
函数名 | 功能 | 时间复杂度 |
---|---|---|
push() | push(x)将元素入队列 | O(logN) |
top() | 获得队首元素 | O(1) |
pop() | 令堆顶元素出队列 | O(logN) |
empty() | 判断优先队列是否为空 | O(1) |
size() | 返回优先队列内元素的个数 | O(1) |
7.stack
函数名 | 功能 | 时间复杂度 |
---|---|---|
push() | push(x)将想入栈 | O(1) |
top() | 获取栈顶元素 | O(1) |
pop() | 弹出栈顶元素 | O(1) |
empty() | 判断栈是否为空 | O(1) |
size() | 获得stack中元素个数 | O(1) |