C++ STL

检查容器是否empty

不要使用过期的iterator

string

字符串转数字:
stoi(字符串,起始位置,n进制),将n进制的字符串转化为十进制
stoi(str, 0, 2); //将字符串str 从0位置开始到末尾的 2进制转换为十进制
string s="1234";
int i=stoi(s);
cout<<i;
————————————————
string s="1234";
int i;
stringstream ss;
ss<<s;
ss>>i;
cout<<i;

数字转字符串:
int a=1234;
string out;
stringstream ss;
ss<<a;
ss>>out;
cout<<out<<endl;
————————————————
int a=1234;
cout<<to_string(a)<<endl; //C++11

//声明迭代器变量,迭代器不检查范围
string::iterator || string::const_iterator
const_iterator begin()const; iterator begin(); //返回string的起始位置
const_iterator end()const; iterator end(); //返回string的最后一个字符后面的位置
const_iterator rbegin()const; iterator rbegin(); //返回string的最后一个字符的位置
const_iterator rend()const; iterator rend(); //返回string第一个字符位置的前面
rbegin和rend用于从后向前的迭代访问,通过迭代器string::reverse_iterator||string::const_reverse_iterator实现
for(auto it=str.begin();it!=str.end();++it) <==> for(auto x:str) //C++11新特性

//获取一行数据
string s;
getline(cin,s);
cout<<s;
//+= 数字会转为ascii码
string s="Hello World!";
s+=10;//10对应的asc码是换行
s+='7'; <==> int a=7;s+=(a+'0');

/*string类的构造函数:*/
string(const char *s);
string(int n,char c);
string s1;
string s2="hello";

/*string类的字符操作:*/
'const' char &operator[](int n)'const';
'const' char &at(int n)'const';
at函数提供范围检查-越界抛出out_of_range异常, 下标运算符[]不提供检查访问
const char *data()const; //返回一个非null终止(不加'\0')的c字符数组
const char *c_str()const; //返回一个以null终止(加'\0')的c字符串
string s2 = s1.c_str(); //char*转字符串
int copy(char *s, int n, int pos = 0) const;
将当前串以pos开始的n个字符拷贝到以s为起始位置的字符数组中,返回实际拷贝的数目

//字符串流处理
通过#include <sstream>头文件中定义的ostringstream和istringstream变量实现
string input("hello,this is a test"); 
istringstream is(input); 
string s1,s2,s3,s4;
is>>s1>>s2>>s3>>s4;//s1="hello,this",s2="is",s3="a",s4="test" 
ostringstream os; 
os<<s1<<s2<<s3<<s4; 
cout<<os.str();

/*string的特性描述:*/
int capacity()const;//返回当前容量(即string中不必增加内存即可存放的元素个数)
int max_size()const;//返回string对象中可存放的最大字符串的长度
int size()const;
int length()const;
bool empty()const;
void resize(int len,char c);//将字符串大小置为len,并用字符c填充不足的部分

/*string类的基本操作:*/
getline(istream &in,string &s);从输入流in中读取字符串到s中,以换行符'\n'分开
string substr(int pos=0,int n=npos)const;//返回以pos开头的n个字符组成的字符串|可切片(-1表示最后)
void swap(string &s2); //交换当前字符串与s2的值
string &assign(const string &s,int start,int n);//start缺省0|n缺省length
string &append(const string &s,int pos,int n);//省略pos和n <=> operator+
int compare(int pos,int n,const string &s,int pos2,int n2)const;//>1<-1=0
iterator erase(iterator it);//删除it指向的字符 | 返回删除后迭代器的位置
iterator erase(iterator first, iterator last);//删除[first,last)间所有字符
string &erase(int pos=0,int n=npos);//删除pos开始的n个字符,返回修改后字符串

find()——查找失败返回string::npos的值
if (str1.find(str2) != string::npos)
    cout << "str1 contains str2" << endl;
else
    cout << "str1 does not contain str2" << endl;
int find(char c, int pos = 0) const;//从pos开始查找字符c在当前字符串的位置
int find(const char *s,int pos = 0) const;//从pos开始查找字符串s在当前串中的位置
int find(const char *s, int pos, int n) const;//从pos开始查找字符串s中前n个字符在当前串中的位置
int find(const string &s,int pos = 0) const;//从pos开始查找字符串s在当前串中的位置
int rfind(const string &s,int pos = npos) const;//从pos开始从后向前查找字符串s中前n个字符组成的字符串在当前串中的位置
int find_first_of(const string &s,int pos = 0) const;//从pos开始查找当前串中第一个在s的前n个字符组成的数组里的字符的位置
int find_first_not_of(const string &s,int pos = 0) const;//从当前串中查找第一个不在串s中的字符出现的位置
int find_last_of(const string &s,int pos = npos) const;//类似find_first_of,从后向前
int find_last_not_of(const string &s,int pos = npos) const;//类似find_first_not_of,从后向前

replace()
string &replace(int p0, int n0,const char *s);//删除从p0开始的n0个字符,然后在p0处插入串s
string &replace(int p0, int n0,const char *s, int n);//...,然后在p0处插入字符串s的前n个字符
string &replace(int p0, int n0,const string &s);//...,然后在p0处插入串s
string &replace(int p0, int n0,const string &s,int pos,int n);//...,然后在p0处插入串s中从pos开始的n个字符
string &replace(int p0, int n0,int n, char c);//...,然后在p0处插入n个字符c
string &replace(iterator first0, iterator last0,const char *s);//把[first0,last0)之间的部分,替换为字符串s
string &replace(iterator first0, iterator last0,const char *s, int n);//...,替换为s的前n个字符。
string &replace(iterator first0, iterator last0,const string &s);//...,替换为串s
string &replace(iterator first0, iterator last0,int n, char c);//...,替换为n个字符c
string &replace(iterator first0, iterator last0,const_iterator first, const_iterator last);

insert()
string &insert(int p0, const char *s);//前4个函数在p0位置插入字符串s中pos开始的前n个字符
string &insert(int p0, const char *s, int n);
string &insert(int p0,const string &s);
string &insert(int p0,const string &s, int pos, int n); 
string &insert(int p0, int n, char c);//此函数在p0处插入n个字符c
iterator insert(iterator it, char c);//在it处插入字符c,返回插入后迭代器的位置
void insert(iterator it, const_iterator first, const_iterator last);//在it处插入[first,last)之间的字符
void insert(iterator it, int n, char c);//在it处插入n个字符c

vector

vector<int> v;//定义一个空vector
vector<int> v(3);//定义一个4个大小的vector,初始为0
vector<int> v(3,7);//定义一个4个大小的vector,初始为6
vector<int> v{1,2,3,4,5};//定义一个vector,数字为1,2,3,4,5
cout << v[2] || v.at(2);

v.push_back(7); //追加元素
v.resize(10); //resize进行重置大小,不赋值默认为0
/*erase删除元素,复杂度为O(n)*/
v.erase(v.begin()); //删除第一个元素
v.erase(--v.end()); //删除最后一个元素
v.front() || v[0] || *v.begin(); //获取第一个元素
v.back() || v[v.size()-1] || *--v.end(); //获取最后一个元素

vector<int> v{1,3,5,-1,4,3,2,0};
sort(v.begin(),v.end(),less<int>());//从小到大
sort(v.begin(),v.end(),greater<int>());//从大到小排序

for(int i=0;i<v.size();i++) cout<<v[i];
for(vector<int>::iterator it=v.begin();it!=v.end();++it) cout<<*it;
for(auto it=v.begin();it!=v.end();++it) cout<<*it;
for(auto x:v) cout<<x;

stack

stack<int> s; //构造
s.push(7); //向栈中添加元素
s.top(); //取栈顶元素,栈空返回-1
s.pop(); //弹出最后一个入栈的元素,无返回值
s.size(); //查看栈中元素个数
s.empty(); //查看栈是否为空

进制转换(十进制转二进制)
int itob(int decimal){
    stack<int> s;
    int res=0;
    while(decimal!=0){
        s.push(decimal%2);
        decimal/=2;
    }
    while(!s.empty()){
        res=res*10+s.top();
        s.pop();
    }
    return res;
}

逆序单词
int main(){
    string str;
    stack<string> s;
    getline(cin,str);
    stringstream ss;//#include <sstream>
    ss<<str;
    while(ss>>str)
        s.push(str);
    while(!s.empty()){
        cout<<s.top();
        s.pop();
        if(s.size()!=0) cout<<" ";
    }
    return 0;
}

queue、priority_queue、deque

queue<int> q; //构造
q.push(7); //在队列末尾追加一个元素
q.front(); //返回第一个元素
q.back(); //返回最后一个元素
q.pop(); //将最先入队的(第一个)元素出队,无返回值
q.size(); //返回队列中元素个数
q.empty(); //返回队列是否为空

清空队列:
//直接用空队列赋值
q=queue<int>(); 
 //遍历出队列
while(!q.empty()) q.pop();
//使用swap是最高效的,定义clear,保持STL容器的标准
void clear(queue<int>& q){
    queue<int>empty;
    swap(empty,q);
}

优先队列: 
priority_queue<Type, Container, Functional>
Type数据类型,Container容器类型(数组实现——vector,deque等,但不能用list。STL默认vector),Functional比较方式
使用自定义的数据类型时才需要传入这三个参数,使用基本数据类型时,只需要传入数据类型,默认是大顶堆 
/*定义优先队列时,> >中间需要有空格,不然编译器会当做是流提取运算符*/
priority_queue <int,vector<int>,greater<int> > q; //升序队列
priority_queue <int,vector<int>,less<int> > q;     //降序队列
Priority_queue<node>q;                            //node为结构体,可以自定义优先级
push( )  //加入一个元素
top( )   //返回优先队列的队顶元素
pop( )   //删除队顶元素
size( )  //返回优先队列中拥有的元素个数
empty( ) //判断一个队列是否为空

struct node{
    int x,y;
    node(){}
    node(int a,int b):x(a),y(b) { }
    operator <(const node &rhs)const{
        if(x==rhs.x)
        	return y>rhs.y; //当x相等时,y大的优先级高 
        return x>rhs.x;    //x大的优先级高
    }
}; 
int main(){
    priority_queue<node> q;
    q.push(node(1,2)); ...... q.push(node(7,8)); 
    while(!q.empty()){
        node temp=q.top();
        q.pop();
        cout<<temp.x<<' '<<temp.y<<endl;
    } 
    return 0;
} 

合并果子——有n堆果子,两两合并直到只剩一堆,每次合并消耗为两堆重量之和,求最小消耗
int main(){
	priority_queue<int,vector<int>,greater<int> > q;
	int n,m,i,ans,p1,p2;
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>m;
		q.push(m);
	}
	for(int i=0;i<n;i++){
		p1=q.top(); q.pop();
		p2=q.top(); q.pop();
		ans+=p1+p2; q.push(p1+p2);
	}
	cout<<ans<<endl;
	return 0;
}

deque(双端队列):可以从任一端添加或移除项;这种混合线性结构提供了单个数据结构中栈和队列的所有能力。
连续内存的容器不能随意扩充,但deque却可以,这是因为它创造了内存连续的假象(每次扩充申请一个新的内存段)。
deque的内存并不真的连续,只是分段连续,当走向段尾时自动跳到下一段内存,支持迭代器++操作(operator++实现)

deque<int> d; //默认构造
deque<int> d1(d); //拷贝构造
deque<int> d2 = d1; //赋值拷贝
deque<int> d3 (5,6); //指定元素个数创建
deque<int> d4(d3.begin()+2, d3.begin()+3); //指定区间创建
deque<int> d5({2,3,4,5}); //指定初始化列表创建
deque<int> d6 = {2,3,4,5};

push_back();
push_front();
pop_back();
pop_front();
empty();
max_size();
resize(10, 5); //重新设定大小(少退多补)
insert(d.begin()+3, 7); //指定位置插入元素
erase(d.begin()+3); //删除指定位置元素
swap(d1);
clear();
emplace(d.end(), 7); //原地构造
emplace_front(7);
emplace_back(7);
shrink_to_fit(); //清空内存

for(auto tmp:d)	cout<<tmp<<endl;
for(auto it=d.begin();it!=d.end();it++)	cout<<*it<<endl;

sort(d.begin(),d.end(),greater<int>());

pair

STL<utility>的模板类pair,表示一个二元组或元素对,其中两个数据值的数据类型可以不同。
pair模板类对象有两个成员:first 和 second 分别表示首元素和尾元素。

#include<utility>
pair<string,double>p1;              //使用默认的构造函数
pair<string,double>p2(“apple”,7.0); //调用构造函数初始化
pair<string,double>p3(p2)           //调用拷贝构造函数
pair<string,double>*p4=new pair<string,double>(“banana”,7.0); //初始化pair指针

若pair的使用比较繁琐,定义多个形同的pair类型的时候,可以时候typedef简化声明:
typedef pair<string,int>student;
student stu1(“Tom”,2019);
student stu2(“Jerry”,2020);

通过 first second 来访问:
pair<string,int>student(“Tom”,2019);
cout<<student.first<<' '<<student.second<<endl;        输出:Tom 2019

如需即时生成一个pair对象,除了直接定义还可以调用<utility>的模板函数——make_pair:
int main(){
    typedef struct pair<string,int> stu;                
    stu stu1=make_pair("Tom",2019);
    cout<<stu1.first<<' '<<stu1.second<<endl;
    stu1.first="Jerry"; stu1.second=2020;
    cout<<stu1.first<<' '<<stu1.second<<endl;
    return 0;
 } 
输出:
Tom 2019
Jerry 2020

Pair 排序:
<utility>中已定义pair的六个比较运算符—— <><=>===!=(first相等时再比较second)
typedef pair<int,int> P;
bool cmp(const P &a,const P&b){ //引用调用
	if(a.first==b.first)
		return a.second<b.second;
	return a.first<b.first;
}//先按照first升序,若first相同按second升序
sort(st,st+n,cmp);

map

map(映射)内部自建红黑树,具有自动排序功能,所以map内的数据是有序的。
map自动建立key--value的对应,key和value可以是任意需要的类型
根据key的值快速查找记录(二分),复杂度为O(log2(N)),插入、删除同理

//基本构造函数
map<string,int>mapstring;
map<int,string>mapint;
map<string,char>mapstring;
map<char,string>mapchar;
map<char,int>mapchar;
map<int,char>mapint;

//插入&遍历
map<int,int> m; //map<int,int>::iterator it;
/* unordered_map<int,int> m;(无序的,哈希结构) */
m[1]=2; m[3]=4; m[5]=6;
mp.insert(pair<int,int>(7,8));
m.insert(map<int,int>::value_type(9,10));
/*insert若key冲突不进行操作,而[]则会覆盖key对应的value*/
for(auto it=m.begin();it!=m.end();it++)
	cout<<it->first<<"->"<<it->second<<endl;
for(it=m.rbegin();it!=m.rend();it++)
	cout<<it->first<<'->'<<it->second<<endl;
for(auto tmp:m)
	cout<<tmp.first<<"->"<<tmp.second<<endl;
/*注意map的index从1开始(m[0]不会报错但是死循环)*/
for(int i=1;i<=m.size();i++)
    cout<<i<<": "<<m[i]<<endl;
↑遍历到m[2]会自动创建一个m[2]=0;,同理还会有m[4]=0;↑
m.size()一开始=3,之所以i能+5是因为:
当i=2时执行完m[2]=0;后m.size()==>4,同理当i=4时执行完m[4]=0;后m.size()==>5
↓要想m.size()保持不变需要改成下面这样↓
for(int i=1;i<=5;i+=2)
	cout<<i<<": "<<m[i]<<endl;

//map转成vector进行排序(用于对value或自定义规则排序)
bool cmp(const pair<int,int> a, const pair<int,int> b){
    return a.second>b.second;
}
int main(){
    unordered_map<int,int> m;
    m[1]=2; m[5]=6; m[3]=4;
    vector<pair<int,int> > v(m.begin(),m.end());
    sort(v.begin(),v.end(),cmp);
    for(auto tmp:v){
        cout<<tmp.first<<tmp.second<<endl;
    }
    return 0;
}

//map的基本操作函数:
begin()         返回指向map头部的迭代器
end()           返回指向map末尾的迭代器
rbegin()        返回指向map尾部的逆向迭代器
rend()          返回指向map头部的逆向迭代器
size()          返回map中元素的个数
max_size()      返回可以容纳的最大元素个数
empty()         如果map为空则返回true
erase()         删除一个元素
Iterator erase(iterator it);//通过一个条目对象删除
Iterator erase(iterator first,iterator last)//删除一个范围
Iterator erase(iterator Key&key);//通过关键字删除
find()          返回key所在位置的迭代器,未找到返回end()
count()         判断指定key是否出现,返回值为01
insert()        插入元素
swap()          交换两个map
clear(<==> map.erase(map.begin(),map.end());
equal_range()   返回特殊条目的迭代器对
get_allocator() 返回map的配置器
lower_bound()   返回键值>=给定元素的第一个位置
upper_bound()    返回键值>给定元素的第一个位置
key_comp()      返回比较元素key的函数
value_comp()     返回比较元素value的函数

/*
map中的元素是自动按Key升序排序,所以不能对map用sort函数;
STL默认用小于号排序,当key是基础数据类型时,支持小于号运算,
但如果key是自定义类型不支持小于号操作,insert等函数在编译时就会报错
*/
【小于号重载——】
typedef struct Student{
    int id;
    string name;
    Student(int i,string n):id(i),name(n) { }
    bool operator<(const Student &obj)const{
        if(id==obj.id){
            if(name==obj.name)
                return false;
            return name<obj.name;
        }
        return id<obj.id;
    }
} stu,*pStu;
int main(){
    map<stu,int> m;
    m.insert(map<stu,int>::value_type(stu(1,"Tom"),97));
    m.insert(map<stu,int>::value_type(stu(2,"Jerry"),99));
    for(auto tmp:m)
        cout<<'('<<tmp.first.id<<','<<tmp.first.name<<')'<<"->"<<tmp.second<<endl;
    return 0;
}
【仿函数——】
typedef struct Student{
    int id;
    string name;
    Student(int i,string n):id(i),name(n) { }
} stu,*pStu;
class sort{
public:
    bool operator() (stu const &_A,stu const &_B)const{//注意const
        if(_A.id == _B.id){
            if(_A.name == _B.name)
                return false;
            return _A.name<_B.name;
        }
        return _A.id<_B.id;
    }
};
int main(){
    map<stu,int,sort> m;//需要添加第三个参数
    m.insert(map<stu,int>::value_type(stu(1,"Tom"),97));
    m.insert(map<stu,int>::value_type(stu(2,"Jerry"),99));
    for(auto x:m)
        cout<<'('<<x.first.id<<','<<x.first.name<<')'<<"->"<<x.second<<endl;
    return 0;
}

set

set, multiset, map, multimap内部采用的都是红黑树(平衡检索二叉树)
set<int> s; //有序
unordered_set<int> uns; //哈希结构,无序,快
insert(key_value)
find(key_value) //没找到返回end()
erase(iterator)
erase(it1,it2)
erase(key_value)
begin()
end()
rbegin()
rend()
clear()
empty()
size()
max_size()
lower_bound(key_value) //返回第一个大于等于key_value的迭代器
upper_bound(key_value) //返回最后一个大于key_value的迭代器

for(auto tmp:s)
	cout<<tmp<<" ";
cout<<endl;
for(auto it=s.begin();it!=s.end();it++)
	cout<<*it<<" ";
cout<<endl;

自定义比较函数——
(1)元素不是结构体:
//自定义比较函数myCmp,重载“()”操作符
struct myCmp{
    bool operator()(const basic_type &a, const basic_type &b){
        return a>b;
    }
};
set<basic_type, myComp>s;
......
set<basic_type, myComp>::iterator it;
(2)如果元素是结构体,可以直接将比较函数写在结构体内:
//重载“<”操作符,自定义排序规则
struct Info{
    string name;
    float score;
    bool operator < (const Info &a) const{
        return score>a.score;
    }
}
set<Info> s;
......
set<Info>::iterator it;

list

1. 如果你需要高效的随机存取,而不在乎插入和删除的效率,使用vector
2. 如果你需要随机存取,而且关心两端数据的插入和删除,则应使用deque
3. 如果你需要大量的插入和删除,而不关心随机存取,则应使用list

list(双向循环链表)——内存不连续,不支持快速随机存取([]和at),因此迭代器只能++--,不能+n或-n。
list<int> li;
li.insert(++li.begin(),7);
li.insert(li.begin(),7,7); //开始位置插入7个7
li.insert(li.begin(),l2.begin(),l2.end());
li.emplace_front(8);
li.emplace_back(9);
li.erase(++li.begin());
li.erase(li.begin(),li.end());
li.splice(++li.begin(), li2); //指定位置插入list
li.assign(n, val) //创建n个结点并全都赋值为val
li.assign(li2.begin(),li2.end())
li.merge(li2 ~~,默认greater<int>()可省略~~ ); //调用结束后li2变为空
li.swap(li2); || swap(li1,li2); //交换两个链表
resize(n) //调用默认构造函数list()将元素加到list末端
resize(n, val) //调用构造函数list(val)进行元素构造
push_back()
push_front()
pop_back()
pop_front()
front() //返回第一个元素
back() //返回最后一个元素
reverse() //把list的元素倒转
unique() //删除list中重复的元素
remove() //从list删除元素
remove_if() //按指定条件删除元素

for(auto tmp:li) cout<<tmp<<endl;
for(auto it=li.begin();it!=li.end();it++) cout<<*it<<endl;
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值