C++中的STL库中有许多好用的工具,通过它们能够快速的实现数据的储存和常见的运算,下面就总结一下一些常用的容器。
string用法
在C++中定义了字符串容器,要用它需要在头文件中声明#include<string>
并且加上 using namespace std;
a)声明
#include<cstdio>
#include<string>
using namespace std;
int main(){
string str1 ="abc";
string str2 = "def";
str1 += str2 // +可以作为字符串的连接符,结果是str1 ="abcdef"
//字符串可以直接用比较运算符比较,比较的是字典顺序
if(str1 > str2){
printf("yes")
}
else{
printf("no");
}
}
需要注意的是,如果要直接读入或者输出一个string类型的,只能够用cin和cout。要用printf输出的话,要转化为char*,用c_str()方法。printf("%s",str.c_str());
b)访问
//通过下标方式访问或者通过迭代器来访问
for(int i=0; i < str.size();i++){
printf("%c",str[i]);
}
string::iterator it = str.begin();
for(it; it < str.end(); it++){
printf("%c",*it);
}
需要注意str.end()不是指字符串的最后一个元素的地址,而是指字符串最后一个元素地址的下一个地址,end()是作为迭代器的末尾标志。
c)插入
string str = "abc"
string str1 ="def";
//法一:insert(pos,str)
str.insert(2,str1); //在下标为2的地方插入str1
printf("%s",str.c_str()); //结果是abdefc
//法二:insert(it,it1,it2),
str.insert(str.begin()+1,str1.begin(),str1.end());
printf("%s\n",str.c_str());//结果是adefbc
d)删除
string str ="abc";
//删除单个元素,erase(it)
str.erase(str.begin()+1);
//删除多个元素,法一:erase(it,it1)//it代表指针
str.erase(str.begin()+2,str.end());
//法二:erase(pos,len)
str.erase(1,2);
e)查找
string str ="abcbc";
int pos = str.find("bc")//返回查找字符串第一次在源串中的位置
int pos1 = str.find("bc",2)//从源串的第2个位开始查找
//当没有找到时,会返回 string::npos,其数值可以代表-1
f)替换 replace()
string str="abc";
string str1 ="def";
//replace(pos.len,str1),把起始位置为pos,长度为len的源子串替换为str1,形成一个新字符串
str.replace(0,2,str1)//结果为defc
//replace(it1,it2,str1),指定替换范围,注意是左闭右开区间
str.replace(str.begin(),str.begin()+2,str1)//结果为defc
vector用法
vector可以将它看为一个变长的数组,而且里面可以存储任意类型的元素。比如数字,字符串,结构体,其他的容器等。需要在头文件上添加#include<vector>
并且要添加using namespace std;
a)声明,添加元素,遍历
声明:vector<type> name,若type是一个容器,要在>后加上一个空格,vector<vector<int> >vec.这是为了和移位运算符区分开
末尾添加:ve.push_back()
遍历:ve[i]或者用迭代器
例子:
#include<iostream>
#include<vector>
using namespace std;
/*
C++中STL标准模板库中vector的用法
*/
int main() {
vector<int> ve;//声明一个向量,里面可以存储int类型
for(int i=0; i < 5; i++){
ve.push_back(i);//用push_back()方法向容器中添加元素
}
for(int i=0; i < ve.size();i++){
//访问方式1:通过下标访问,类似于数组
cout<<ve[i];
}
//访问方式2:通过迭代器
for(vector<int>::iterator it = ve.begin();it != ve.end(); it++ ){
cout<<*it;
}
return 0;
}
b)大小,删除,插入,清除
容器大小:ve.size()
删除末尾元素: ve.pop_back():
清除:ve.erase()
int size = ve.size();//给出容器的大小
ve.pop_back();//删除最后一个元素
ve.insert(ve.begin(),10);//在0位置插入10,注意这里的参数是指针
ve.erase(ve.begin())+2);//清除位置是2的元素
ve.erase(ve.begin(),ve.begin()+3)//清除[0,3)的元素
ve.clear();//清除所有元素,等价于ve.erase(ve.begin(),ve.end())
set用法
set在数学中是集合的意思,在C++中集合有一下特征:内部有序且不含重复元素。使用方法,要加上#include<set>
和using namespace std;
a)声明,访问,添加元素
声明:set<type> name//注意,当set中的元素为容器的时候,要在>后加一个空格。set<vector<iint> >name 和移位运算区别
添加元素 insert()
遍历只能迭代器
#include<iostream>
#include<set>
using namespace std;
int main(){
//声明一个set
set<int>s;
//向set中添加元素
s.insert(3);
s.insert(5);
s.insert(1);
//set中的元素遍历只能够是通过迭代器来实现
set<int>::iterator it = s.begin();
for(it;it != s.end(); it++){
cout<<*it;
}
} //输出的结果是有序的,为1,3,5
b)删除,查找,清空
删除:erase(it),erase(value),erase(fist,end)
查找:find(value)
清空 :clear()
#include<iostream>
#include<set>
using namespace std;
int main(){
//声明一个set
set<int>s;
//向set中添加元素
s.insert(3);
s.insert(5);
s.insert(1);
s.insert(4);
s.insert(9);
//删除单个元素,erase(it),it为所需要删除元素的迭代器
//s.find(value),find()是找到set中值为value的迭代器
s.erase(s.find(1));
//删除单个元素,erase(value)
s.erase(3);
//删除多个元素,erase(first,end),其中first,end为要删除的区间的起始迭代器
//范围是[first,end)
s.erase(s.find(5),s.end());//删除了5,9
set<int>::iterator it = s.begin();
//输出的结果为4
for(it;it != s.end(); it++){
cout<<*it;
}
//清空集合中的元素
s.clear();
cout<<s.size();//输出为0
}
map用法
map可以将任何基本类型(包括STL容器)映射到任何基本类型(包括STL容器),
在使用时要加上头文件#include<map>
以及using namespace std;
a)声明,赋值,遍历
#include<iostream>
#include<map>
using namespace std;
int main(){
//声明map
map<int,string>st;
//赋值,和数组类似
st[0] ="str1";
st[1] ="str3";
st[2] ="str2";
//通过键名来遍历值
for(int i=0; i<st.size(); i++){
cout<<st[i]<<endl;
}
//用迭代器来遍历,it->first代表键,it->second代表值
map<int,string>::iterator it = st.begin();
for(it;it !=st.end(); it++ ){
cout<<it->first<<"=>"<<it->second<<endl;
}
}
b)查找,删除,清空
//find()函数,找出对应元素的迭代器
map<int,string>::iterator it = st.find(0);
cout<<it->first<<" "<<it->second<<endl;
//删除单个元素,erase(it)
st.erase(st.find(0));
//删除单个元素,erase(键名)
st.erase(1);
//删除一个范围内的元素
st.erase(st.begin(),st.end());//相当于st.clear()
cout<<st.size();
queue用法
队列(queue)作为一种先进进先出的数据结构,有着广泛的用途。比如在广度优先搜索中,就会用到queue,下面总结一下queue的常见操作
1)插入,访问,删除
#include<cstdio>
#include<queue>
using namespace std;
int main(){
queue<int>q;//声明一个队列q;
q.push(1);
q.push(2);
q.push(3); //push操作:向队尾添加元素
if(!q.empty()){ //进行pop,front操作前先判断队列是否为空
int head = q.front(); //front操作:访问队首元素
int tail = q.back();//back操作:访问队尾元素
printf("%d %d\n",head,tail); //结果是1 3
q.pop();//pop操作,删除队首的元素
printf("%d\n",q.front());//再次访问队首,结果为2
}
}
priority_queue用法
priority_queue又叫做优先队列,它的底层是通过堆来实现的。保证了队首的元素一定是优先级最高的。优先队列没有front()和back()操作,只能够通过top()来访问队首的元素
1)声明,定义
#include<queue>
priority_queue<int> pq;
2)插入,访问
pq.push(1);
pq.push(2);
pq.push(3);
printf("%d",pq.top());//结果为3
关于优先级的问题
默认情况下,优先队列是将最大的元素放在队首的,所谓最大元素,对于普通的类型如int,double等,就是数值大的优先级高,对于char类型的话,就是按照字典大小。
其实优先队列一般有两种声明方式
priority_queue<int>
priority_queue<int,vector<int>,less<int>>
这两种声明方式是等价的,对于第二种声明方式,第一个参数int说明队列中存放的数据类型是int性,vector<int>
是堆的底层实现(优先队列是通过堆来实现的),后面的less<int>
就指明了优先级,less<int>
表明将优先级高的放在队首,与之相反的是greater<int>
,表明将优先级低的放在队首。
对于非一般类型的数据,比如结构体,又该如何设置优先级呢?
#include<cstdio>
#include<queue>
using namespace std;
struct student{
int id;
int score;
//设置一个函数,对student类型的操作符<进行重载
friend bool operator < (student a,student b){
return a.score < b.score;//将分数高的放在队首
}
//构造函数
student(int _id,int _score):id(_id),score(_score){}
};
int main(){
student a = student(1,90);
student b = student(2,80);
priority_queue<student> pq;
pq.push(a);
pq.push(b);
student t = pq.top();
printf("%d:%d",t.id,t.score);
}