6.1 vector的常见用法详解
vector是一个“长度根据需要而自动改变的数组”
如果碰到普通数组超内存的情况,使用vector方法让我们方便很多。
可以以连接表的方式存储图
头文件:#include
(1)vector 的定义
单独定义一个vector
vector name;
typename也可以是一个容器
vector<vector > name
可以当作二维数组理解
(2)vector容器内元素的访问
两种,一是下标访问,二是通过迭代器访问
1.通过下标访问,如vector vi,直接访问vi[i],i等于i-sizeof(vi).
2.通过迭代器访问,迭代器类似于指针,其定义为
vector<typename>::iterator it;
可以通过*it来访问容器内的元素
美国人思维比较喜欢左闭右开,end()是指尾元素的下一个地址。
#include<cstdio>
#include<vector>
using namespace std;
int main (){
vector<int > vi;
for(int i=1;i<=5;i++)
vi.push_back(i);
for(vector<vi>::iterator it=vi.begin();it!=vi.end();it++){
printf("%d",*it);
}
return 0;
}
STL只有vector与string有vi.begin()加整数的写法
(3)vector常用函数
1.push_back()
push_back(x),在vector后面加元素,时间复杂度O(1)
2.pop_back()
有添加就会有删除,删除vector尾元素
3.size()
获取vector中元素的个数
4.clear()
清空vector所有的元素
5.insert()
insert(it,x),用来在vector的任意迭代器it处添加一个元素x,
#include<cstdio>
#include<vector>
using namespace std;
int main (){
vector<int > vi;
for(int i=1;i<=5;i++)
vi.push_back(i);
vi.insert(vi.begin()+2,6);
for(int i=0;i<vi.size();i++)
printf("%d ",vi[i]);
return 0;
}
6.erase()
两种用法:删除单个元素,删除一个区间所有元素
删除单个元素:erase(it) 删除迭代器it处的元素
#include<cstdio>
#include<vector>
using namespace std;
int main (){
vector<int > vi;
for(int i=5;i<=9;i++)
vi.push_back(i);
vi.erase(vi.begin()+3);
for(int i=0;i<vi.size();i++)
printf("%d ",vi[i]);
return 0;
}
删除区间所有元素:erase(first,last),即删除[first,last)内所有元素
#include<cstdio>
#include<vector>
using namespace std;
int main (){
vector<int > vi;
for(int i=5;i<=9;i++)
vi.push_back(i);
vi.erase(vi.begin()+1,vi.begin()+4);
for(int i=0;i<vi.size();i++)
printf("%d ",vi[i]);
return 0;
}
(4)vector常用用途
1.储存数组
2.用邻接表存储图
6.2 set的常见用法
set翻译为集合,是一个内部自动有序且不含重复元素。
需添加#include
1.set定义
set name;
set name //node结构体
set数组与vector相同
set s[arraysize]
这样s[0]到s[arraysize-1]中每一个都是一个容器set
2.set内元素的访问
set只能通过迭代器访问
set ::iterator it;
由于除了vector与string支持*(it+i)的访问方式,所以只能枚举
#include<cstdio>
#include<set>
using namespace std;
int main (){
set<int > st;
st.insert(3);
st.insert(5);
st.insert(3);
st.insert(2);
for(set<int >::iterator it=st.begin();it!=st.end();it++){ //不支持it<st.end()的写法
printf("%d ",*it);
}
return 0;
}
3 . set常用函数
(1)insert()
insert(x) 可将x插入set容器中。
(2)find()
find(value) 返回set中对应值value的迭代器。
返回值为指向键等于key的元素的迭代器,否则返回end()
#include<cstdio>
#include<set>
using namespace std;
int main (){
set<int > st;
st.insert(5);
st.insert(4);
set<int >::iterator it=st.find(1);
printf("%d\n",*it);
return 0;
}
(3)erase()
删除单个元素和区域所有元素
删除单个元素可通过find(),也可直接删除
区间所有元素删除:
#include<cstdio>
#include<set>
using namespace std;
int main (){
set<int > st;
st.insert(5);
st.insert(4);
st.insert(10);
set<int >::iterator it=st.find(5);
st.erase(it,st.end());
for(it=st.begin();it!=st.end();it++)
printf("%d ",*it);
return 0;
}
(4)size()
用来获取set的元素
(5)clear()
3.set常见用途
主要用途:去重自动排序
set中元素是唯一的。若需要不去重用multiset。unordered_set
6.3 string的常见用法
头文件#include
1.string 的定义
string str;
string str=“abcd”;
2.string中内容的访问
#include<cstdio>
#include<string>
using namespace std;
int main (){
string str="abecd";
printf("%c",str[2]);
return 0;
}
如果要读入和输出只能用cin和cout,若要用printf,需要转换
(2)通过迭代器访问,并可以用*it来访问string的每一位
#include<cstdio>
#include<string>
using namespace std;
int main (){
string str="abecd";
for(string::iterator it=str.begin();it!=str.end();it++)
printf("%c",*it);
return 0;
}
string与vector一样支持直接对迭代器进行加减
3.string常见函数
(1)operator+=,string相加等于string相接
(2)compare operator
两个string可直接使用==、!=、<、>等,比较规则是字典序
(3)length()与size(),返回string的长度
(4)insert(),有很多用法
insert(pos,string) //pos为位置
insert(it,it2,it3) //it是需要插入的位置,it2、it3是首尾迭代器
#include<cstdio>
#include<iostream>
#include<string>
using namespace std;
int main (){
string str1="momo",str2="dada";
str1.insert(str1.begin()+2,str2.begin()+1,str2.end());
cout<<str1<<endl;
return 0;
}
(5)erase()
删除单个元素、区间元素
前两种与其他容器相同
str.earse(pos,length) //pos是位置,length是删除的个数
#include<cstdio>
#include<iostream>
#include<string>
using namespace std;
int main (){
string str1="momodada";
str1.erase(3,2);
cout<<str1<<endl;
return 0;
}
(6)clear()
(7)substr()
substr(pos,len) 返回从pos号开始,长度为len
(8)string::npos
string::npos是一个常数-1或者4294967295
用以作用find函数失配时的返回值
(9)find()
str.find(str2),str2是str的字串时,返回其在str第一次出现的位置,否则返回string::npos
(10)replace()
str.replace(pos,len,str2).把str从pos位置开始,长度为len的子串替换成str2.
str.replace(it1,it2,str2).把str的迭代器[it1,it2)范围的子串替换str2.
PAT 1060
#include<iostream>
#include<string>
using namespace std;
int n; //有效位数
string deal(string s,int &e){
int k=0; //s的下标
while(s.length()>0&&s[0]=="0")
s.erase(s.begin()); //去掉前导数
if(s[0]=="."){ //去掉前导0,是.说明是小数
s.erase(s.begin());
while(s.length()>0&&s[0]=="0")
s.erase(s.begin());
e--;
}
else
{
while(k<s.length()&&s[k]!="."){ //如果不碰到".",e++
k++;
e++;
}
if(k<s.length()){//碰到小数点
s.erase(s.begin()+k);
}
if(s.length==0) //前导数去掉,长度为0,说明这个数为0
e=0;
int num=0;
k=0;
string res;
while(num<n){ //只要精度还没有到n
if(k<s.length())
res+=s[k++];
else
res+='0';
num++;
}
}
return res;
}
int main (){
string s1,s2,s3,s4;
cin>>n>>s1>>s2;
int e1=0,e2=0;//s1与s2的指数
s3=deal(s1,e1);
s4=deal(s2,e2);
if(s1==s2&&e1==e2){
cout<<"YES 0."<<s3<<"*10^"<<e1<<endl;
}
else
cout<<"NO.0"<<s3<<"*10^"<<e1<<"0."<<s4<<"*10^"<<e2<<endl;
return 0;
}
6.4 map的常用用法
map翻译成映射,可以将任何基本类型(包括STL容器)映射到基本类型(包括STL容器)
头文件:#include
#include<cstdio>
#include<map>
using namespace std;
int main (){
map<char,int >mp;
mp['c']=20;
mp['c']=30;
printf("%d\n",mp['c']);
return 0;
}
(2)通过迭代器访问
与其他STL容器相同
map<typename1,typename2> ::iterator it;
必须通过一个it来访问key和value.
实际上,map可通过it->first来访问key,it->second来访问value
#include<cstdio>
#include<map>
using namespace std;
int main (){
map<char,int >mp;
mp['c']=20;
mp['m']=30;
mp['a']=40;
for(map<char,int>::iterator it=mp.begin();it!=mp.end();it++){
printf("%c %d\n",it->first,it->second);
}
return 0;
}
map会以键值而从小到大自动排序,这是由于map内部是由红黑树实现的(set也是)。
3.map常数解析
(1)find()
find(key)返回键是key的迭代器
(2)erase()
删除单个元素两种方法:mp.erase(it)和mp.erase(key)
删除一个区域的所有元素:mp.erase(first,second)
(3)size()
来获取map中映射的对数
(4)clear()
4.map常见用途
(1)需要建立字符串与整数之间映射的题目
(2)判断大整数或者其他类型是否存在
(3)字符串与字符串的题也可能遇到
map的键与值是唯一的,而需要一个键对应多个值,就只能用multimap。另外,C++还支持unordered_map使其只映射而不按照key排序
6.5 queue的常见用法
queue翻译为队列,实现了一个先进先出的容器
1.queue的定义:
头文件#include
queue name
2.容器内的访问
由于queue是一个先进先出的容器,所以他只能访问头元素front()和尾元素back()
3.queue的常用函数
(1)push()
push(x)将x入队
(2)front()、back()
分别获得队首元素、队尾元素
(3)pop()
pop()让首元素出队
(4)empty()
检查是否为空,空则返回true,非空则返回false
(5)size()
元素的个数
4.常见用途
(1)需要实现广度优先搜索,可以用queue代替。
(2)在用front()、pop()时,先要用empty()判断是否为空,否则可能因为队空而出现错误
(3)deque和优先队列(priority_queue),前者是首尾皆可插入、删除,后者使用堆排列将最大元素置于队首
6.6 priority_queue的常见解法
队首元素一定是优先级最高的那个
1.定义:
#include
2.元素的访问:
没有front()与back(),只有top()
3.常用函数
(1)push()
(2) top() 获得队首元素
(3)pop() ,令队首元素出队
(4)empty() 检查是否为空
(5)size()
4.优先级的设置
less 表示数字大的优先级大
greater表示数字小的优先级大
priority_queue<int ,vector ,less > q;
(2)结构体的优先级设置:
重载:重载是指对已有的运算符进行重新定义,也就是说,改变小于号的功能
struct fruit{
string name;
int price;
friend bool operator<(fruit f1,fruit f2){
return f1.price>f2.price;
}
};
优先队列的这个函数与sort函数cmp函数的效果是恰恰相反的
比较类中的参数,需要加上const、&。
5.priority_queue的用途
(1)解决一些贪心问题,Dijkstra算法进行优化
(2)top前,要先判断是否为空(empty)
6.7 stack的常见用法详解
stack翻译成栈,后进先出的容器。
1.定义:
#include
stackname
2.容器内的访问元素
只能通过top()访问栈顶元素
3.stack常用函数
(1)push.()
(2) top.()
(3) pop.()
(4)empty.()
(5)size()
5.常见用途:
模拟一些递归
6.8 pair的常见用法
想要把两个元素绑在一起,却又不想用struct
头文件:#include
#include<cstdio>
#include<algorithm>
using namespace std;
int main (){
int a[10];
for(int i=0;i<6;i++)
a[i]=i;
reverse(a,a+6);
for(int i=0;i<6;i++)
printf("%d ",a[i]);
return 0;
}
也可以对字符串进行转换
6.9.4 next_permutation()
给出一个序列在全排列中的下一个序列
#include<cstdio>
#include<algorithm>
using namespace std;
int main (){
int a[10]={1,5,6};
do{
printf("%d %d %d\n",a[0],a[1],a[2]);
}while(next_permutation(a,a+3));
return 0;
}
6.9.5 fill()
fill()可以把数组或容器中的某一段区间赋为某一相同的值。和memset不同的是,可以是任意值。
6.9.6 sort()
sort(首元素地址,尾元素地址的下一位,比较函数)
6.9.7 lower_bound()、upper_bound()
lower_bound()和upper_bound()需要在一个有序的容器里;
lower_bound(first,last,val),寻找数组或容器中[first,last)范围内第一个大于等于val的位置,如果是数组返回该位置的指针,如果是容器,返回迭代器。
upper_bound()第一个大于val的位置
如果求下标,即减去首地址即可