STL初识之vector存放数据
//创建vector对象
vector<int> v;
//遍历方式1
vector<int>::interator vBegin=v.begin();//起始迭代器,指向容器第一个元素
vector<int>::interator vEnd=v.end();//结束迭代器,指向容器最后一个元素的后一位
while(vBegin!=vEnd){
cout<<*vBegin<<endl;
vBegin++;
}
//遍历方式2
for(vector<int>::interator it=v.begin();it!=v.end();it++)
{
cout<<*it<<endl;
}
//遍历方式3
//用容器自带的for_each算法
void MyPrint(int val)
{cout<<int<<endl;}
//调用回调函数,回调函数形参等待把迭代器指向的值传过去,所以迭代器指向的容器的值和该回调函数的值类型要一致
for_each(v.begin(),v.end(),MyPrint);
//嵌套容器
vector <vector<int>> v;
vector<int> v1;
vector<int> v2;
vector<int> v3;
v.push_back(v1);
v.push_back(v2);
v.push_back(v3);
for(vector <vector<int>>::interator it=v.begin();it!=v.end();it++){
for(vector<int> vit=(*it).begin();vit!=(*it).end();vit++)
{
cout<<*vit<<endl;
}
}
string容器
string其实就是一个封装好的类,内部就是维护一个字符数组
构造函数调用:
//空构造
string str();
//有参构造
const char *s="hello";
string str1(s);
//利用另一个对象初始化类对象
string str2(str1);
//使用n个相同的字符进行初始化,下面结果为aaaaaaaaaa
string str3(10,'a');
赋值操作
函数原型:
string& operator=(const char* s);//char* 类型字符串赋值给当前字符串
string& operator=(const string &s);//字符串s赋值给当前字符串
string& operator=(char c);//字符c赋值给当前字符串
string& assign(const char* s);//字符串s赋值给当前字符串
string& assign(const char* s,int n);//字符串s的前n个字符赋值给当前字符串
string& assign(const string &s);//字符串s赋值给当前字符串
string& assign(int n,char c);//把n个字符c赋值给当前字符串
字符串拼接
函数原型:
string& operator+=(const char* s);//重载+=运算符,直接拼接char*类型字符串
string& operator+=(const char c);//重载+=运算符,直接拼接字符c
string& operator+=(const string &s);//重载+=运算符,直接拼接s字符串
string& append(const char* s);//把char*类型字符串拼接到当前字符串末尾
string& append(const char* s,int n);//把char*字符串的前n个字符拼接到当前字符串末尾
string& append(const string &s);//把字符串s拼接到当前字符串末尾s
string& append(const string &s,int pos,int n);//字符串s中从pos开始的n个字符拼接到当前字符串末尾
查找和替换
函数原型:
int find(const string &str,int pos=0) const;//查找str第一次出现的位置,从pos开始查找
int find(const char* s,int pos=0) const;//查找s第一次出现的位置,从pos开始查找
int find(const char* s,int pos=0,int n) const;//从pos查找s前n个字符第一次出现的位置
int find(const char c,int pos=0) const;//查找字符c第一次出现的位置,从pos开始查找
int rfind(const string &str,int pos=npos) const;//查找str最后一次出现的位置,从npos开始查找
int rfind(const char* s,int pos=npos) const;//查找s最后一次出现的位置,从npos开始查找
int rfind(const char* s,int pos=npos,int n) const;//从pos查找s前n个字符最后一次出现的位置
int rfind(const char c,int pos=npos) const;//查找字符c最后一次出现的位n置,从pos开始查找
string& replace(int pos,int n,const string& str);//替换从pos开始的n个字符为字符串str
string& replace(int pos,int n,const char* s);//替换从pos开始的n个字符为字符串s
字符串比较
函数原型:
//通过逐个对比字符的ASIIC码的大小
//=返回0
//>返回1
//<返回-1
int compare(const string &s)const;
int compare(const char* s)const;
字符存取
函数原型:
char& operator[](int n);//[]获取字符
char& at(int n);//at方法获取快递
字符串插入和删除
函数原型:
string& insert(int pos,const char*s);//插入字符串
string& insert(int pos,const string &str);//插入字符串
string& insert(int pos,int n,char c);//指定位置插入n个c字符
string& erase(int pos,int n=npos);//删除从pos开始的n个字符
string子串(截取字符串)
函数原型:
string substr(int pos=0,int n=npos)const;//返回从pos开始的n个字符组成的字符串
vector容器
和数组不同的是,vector容器可以自动拓展空间(找一个更大的空间)
构造函数
函数原型:
vector<T> v; //模板类实现,默认构造函数
vector<T> v(v.begin(),v.end()); //把别的vector容器里[v.begin(),v.end())区间的元素拷贝给本身
vector<T> v(n,elem); //将n个elem拷贝给本身
vector<T> v(const vector &vec); //拷贝构造函数
赋值操作
函数原型:
vector& operator=(const vector &vec);//重载=
assign(v.begin(),v.end());//从别的容器里[v.begin(),v.end())区间的元素拷贝给本身
assign(n,elem);//将n个elem拷贝给本身
容量和大小
函数原型:
bool empty(); //判断是否为空(返回真则为空)
capacity(); //获取容器容量
size(); //获取容器中元素个数
resize(int num); //重新指定容器长度为num,如果容器变长,默认值填(0)充新位置
//容器变短,则删除超出容器长度的元素
resize(int num,elem);//重新指定容器长度为num,如果容器变长,以elem填充新位置
//容器变短,则删除超出容器长度的元素
插入和删除
函数原型:
push_back(elem); //尾部插入元素
pop_back(); //尾部删除最后一个元素
insert(const_iterator pos,elem); //迭代器指向位置pos(前面)插入元素elem,eg:insert(v.begin()+3,1000);
insert(const_iterator pos,int n,elem); //迭代器指向位置pos(前面)插入n个元素elem
erase(const_iterator pos); //删除迭代器指向的元素
erase(const_iterator start,const_iterator end); //删除迭代器从start到end之间的元素
clear(); //删除容器中所有元素
数据存取
函数原型:
at(int index); //返回索引位置的数据
operator[](); //重载[],返回中括号里面索引的元素,如v[3],和数组、字符串取元素类似
front(); //返回容器中第一个元素
back(); //返回容器最后一个元素
互换容器
实现两个容器内元素互换
函数原型:
swap(vec);//将vec与本身元素互换
当容器里的元素减的很少,其容量是富余的,可以利用swap来减少内存空间
//假设v容量为1000,但size为3,此时vector<int> (v)创建匿名对象,并且以v容器元素进行初始化
//但是匿名对象容器的容量是根据v的元素个数来决定的
//只有三个元素,所以匿名对象容器的容量很小
//使用swap其实就是交换了两个容器
//交换之后的v容器其实就是刚创建的匿名对象,而之前v指向的容器变成匿名对象,被系统销毁了
//这就直接减小了容器的内存
vector<int> (v).swap(v);
预留空间
函数原型:
//当提前知道容器需要存放大量数据,提前预留空间可以减少容器重新开辟内存的次数
reserve(int len);//容器预留len个长度元素,预留位置不初始化,元素不可访问
deque容器
和vector容器的区别是,deque容器是一个双头的容器,有自己头部插入和删除的方法,相比于vector来说,头部插入和删除效率更快,但是读取数据没有vector快。
deque也有自动拓展功能,但是不同的是它的存储空间不一定是连续的,它有一个中控器,中控器里面存放的是每个缓冲区的首地址,容器所有的数据都在这些缓冲区,当需要拓展容量,只需要重新找一块不用的内存作为缓冲区,并且在中控器加上这个缓冲区的首地址就行。
构造函数
函数原型:
deque<T> deqT; //模板类实现,默认构造函数
deque<T>(d.begin(),d.end()); //把别的deque容器里[d.begin(),d.end())区间的元素拷贝给本身
deque<T>(n,elem); //将n个elem拷贝给本身
deque<T>(const deque& deq); //拷贝构造函数
注:当需要在函数传递的时候加const保证容器里内容不被改变时,需要使用const_iterator迭代器
赋值操作
函数原型:
deque& operator=(const deque &vec);//重载=
assign(d.begin(),d.end());//从别的容器里[d.begin(),d.end())区间的元素拷贝给本身
assign(n,elem);//将n个elem拷贝给本身
大小操作
函数原型:(和vector相比,没有获取容量)
bool empty(); //判断是否为空(返回真则为空)
size(); //获取容器中元素个数
resize(int num); //重新指定容器长度为num,如果容器变长,默认值填(0)充新位置
//容器变短,则删除超出容器长度的元素
resize(int num,elem);//重新指定容器长度为num,如果容器变长,以elem填充新位置
//容器变短,则删除超出容器长度的元素
插入和删除
函数原型:
push_back(elem); //尾部插入元素elem
pop_back(); //尾部删除最后一个元素
push_front(elem); //头部插入元素elem
pop_front(); //头部删除一个元素
insert(const_iterator pos,elem); //迭代器指向位置pos(前面)插入元素elem,eg:insert(v.begin()+3,1000);
insert(const_iterator pos,iterator begin,iterator end); //在pos插入[beg,end)之间的元素
insert(const_iterator pos,int n,elem); //迭代器指向位置pos(前面)插入n个元素elem
erase(const_iterator pos); //删除迭代器指向的元素
erase(const_iterator start,const_iterator end); //删除迭代器从start到end之间的元素
clear(); //删除容器中所有元素
数据存取
函数原型:
at(int index); //返回索引位置的数据
operator[](); //重载[],返回中括号里面索引的元素,如d[3],和vector操作一样
front(); //返回容器中第一个元素
back(); //返回容器最后一个元素
deque 排序
对于支持随机访问的迭代器的容器,都可以使用sort算法直接排序,vector也可以
函数原型:
sort(iterator beg,iterator end); //对beg和end区间内元素排序,默认是升序,是全局函数,不是成员函数
可以使用二元谓词修改排序规则:见函数对象相关内容
stack(栈)容器
栈容器必须符合先进后出的原则,只有在栈顶的元素才可以被访问,因此,栈也不能被遍历。入栈为push,出栈为pop,一旦出栈,栈中就不存在该元素了
构造函数
函数原型:
stack<T> stk; //默认构造函数
stack<T> (const stack<T> &stk); //拷贝构造函数
赋值操作
函数原型:
stack& operator=(const stack<T> &stk);//重载=
数据存取
函数原型:
push(elem); //入栈,向栈顶添加元素
pop(); //出栈,从栈顶移除一个元素
top(); //返回栈顶元素
大小操作
函数原型:
empty(); //判断栈是否为空
size(); //返回栈大小
queue 队列
队列和栈不同,他有两头,称为队头和队尾,队头只能出队,队尾只能入队,只有两头可以对队容器进行操作,不可以遍历,且遵守先进先出的原则。
构造函数
函数原型:
queue <T> que; //默认构造函数
queue <T> (const queue<T> &que); //拷贝构造函数
赋值操作
函数原型:
queue & operator=(const queue <T> &que);//重载=
数据存取
函数原型:
push(elem); //入队,向队尾添加元素
pop(); //出栈,从队头移除一个元素
front(); //返回队头元素
back(); //返回队尾元素
大小操作
函数原型:
empty(); //判断队是否为空
size(); //返回队大小
list链表
链表是根据结点来进行维护的,每个结点又分为数据域和指针域,数据域存放元素,指针域存放的是指向下一个元素的地址,这样,每个结点通过指针连接起来,所以叫链表
优势:可以快速在任意位置进行插入和删除元素,其实就是修改对应位置上一个节点的指针地址指向插入的结点,然后插入结点指针指向下一个节点。删除的时候,直接把某个位置上一个节点直接指向该位置下一个节点就行。
缺点:遍历速度没有数组快。占用空间比数组大,因为还要存放地址。
STL中的链表是一个双向循环链表
其每个结点存放了两个地址,prev指向上一个结点,next指向下一个节点,可以正着走,也可以反着走,且最后一个节点的next指向第一个节点,第一个结点的prev指向最后一个结点,所以是双向循环。
链表中迭代器只能前移后移,是一个双向迭代器
插入和删除迭代器不会失效,但是vector可能会失效,当vector重新开辟内存进行拓展,原有的迭代器就失效了。使用迭代器不能像vector和qeque一样begin()+n;只能使用++或者–(+1不可以)。
构造函数
函数原型:
list<T> deqT; //模板类实现,默认构造函数
list<T>(l.begin(),l.end()); //把别的list容器里[l.begin(),l.end())区间的元素拷贝给本身
list<T>(n,elem); //将n个elem拷贝给本身
list<T>(const list& l); //拷贝构造函数
赋值和交换
函数原型:
list& operator=(const list &l); //重载=
assign(l.begin(),l.end()); //从别的容器里[l.begin(),l.end())区间的元素拷贝给本身
assign(n,elem); //将n个elem拷贝给本身
swap(l); //将l与本身元素交换
大小操作
函数原型:(和vector相比,没有获取容量)
bool empty(); //判断是否为空(返回真则为空)
size(); //获取容器中元素个数
resize(int num); //重新指定容器长度为num,如果容器变长,默认值填(0)充新位置
//容器变短,则删除超出容器长度的元素
resize(int num,elem);//重新指定容器长度为num,如果容器变长,以elem填充新位置
//容器变短,则删除超出容器长度的元素
插入和删除
函数原型:
push_back(elem); //尾部插入元素elem
pop_back(); //尾部删除最后一个元素
push_front(elem); //头部插入元素elem
pop_front(); //头部删除一个元素
insert(const_iterator pos,elem); //迭代器指向位置pos(前面)插入元素elem,eg:insert(v.begin()+3,1000);
insert(const_iterator pos,iterator begin,iterator end); //在pos插入[beg,end)之间的元素
insert(const_iterator pos,int n,elem); //迭代器指向位置pos(前面)插入n个元素elem
erase(const_iterator pos); //删除迭代器指向的元素,返回下一个数据位置
erase(const_iterator start,const_iterator end); //删除迭代器从start到end之间的元素,返回下一个数据位置
remove(elem); //删除容器中所有与elem匹配的元素
clear(); //删除容器所有元素
数据存取
函数原型:
front(); //返回容器中第一个元素
back(); //返回容器最后一个元素
不能使用[]或者at方法访问,因为链表不是使用的连续空间存储。
反转和排序
函数原型:
reverse(); //反转链表
sort(); //链表排序,是成员函数里的排序,默认从小到大
**此处的sort不是标准算法,和deque的排序不一样。**不支持随机访问的迭代器,内部一般有自己的排序算法
怎么降序:
bool compare(int v1,int v2)
{return v1>v2;}
//只需要传递这种函数,告诉函数前面的数大于后面的数,就会降序
//实际上传递的是排序规则
l.sort(compare);
//例如自定义类型排序,对于一个类Car,里面右num,age,name三个属性
//age升序
bool compare(Car &c1,Car &c2)
{
//num相同时,按照age降序
if(c1.num==c2.num){return c1.age>c2.age;}
else{return c1.num<c2.num;}
}
set和multiset容器
该容器,当数据放入的时候就自动进行排序了,set不允许包含重复的元素,multiset可以放重复元素,底层实现是二叉树,是关联式容器。
没有尾插法,尾删法,只能插入
构造函数
函数原型:
set<T> st; //默认构造函数
set<T> st(const set &st1); //拷贝构造
赋值
函数原型:
set& operator=(const set<T>& st);
大小和交换
函数原型:
size(); //返回容器大小
empty(); //判断容器是否为空
swap(); //交换容器
插入和删除
函数原型:
insert(elem); //插入一个元素
clear(); //删除所有元素
erase(pos); //删除指定位置元素
erase(begin,end); //删除区间内的元素
erase(elem); //删除容器中的值为elem的元素
查找和统计
函数原型:
find(elem); //查找到则返回该位置迭代器,否则返回end迭代器
count(elem); //统计元素为elem的个数,对于set容器,结果只有0,1
和multiset区别
主要区别就是multiset可以插入重复数据,set再插入的时候会返回插入的结果是否成功,但是multiset插入不会检测是否成功。
//返回的是pair类型数据,包含一个迭代器和一个bool类型变量
pair<set<T>::iterator,bool> ret = st.inverse(elem);
//以下可以拿到bool类型数据
ret.second;
对组创建
函数原型;
pair<type,type> p(value1,value2);
pair<type,type> p = makepair(value1,value2);
//取数据使用
p.first;
p.second;
排序
内置数据类型
set容器默认排序是从小到大,可以利用仿函数修改排序规则
//首先定义一个类,用于设置排序规则
class MyCompare{
public:
bool operator()(int v1,int v2)
{
return v1>v2;//降序的时候前面的数大于后面的数
}
};
//在创建的时候把设置规则的类也指定好
set<int,MyCompare> st;
st.insert(1);
st.insert(5);
st.insert(7);
st.insert(3);
for(set<int,MyCompare>::iterator it=st.begin();it!=st.end();it++)
{
cout<<*it<<endl;
}
自定义数据类型
如果有一个类,需要插入到set容器中,就会出现问题,因为容器不知道怎么对该类进行排序,此时就需要先指定排序规则。
class Person
{
public:
Person(string name,int age)
{
this->name=name;
this->age=age;
}
string name;
int age;
};
class comparePerson{
public:
bool operator()(const Person &p1,const Person &p2)
{
return p1.age>p2.age;//按照年龄进行降序
}
};
Person p1("a",18);
Person p2("b",19);
Person p3("c",16);
set<Person,comparePerson> st;
st.insert(p1);
st.insert(p2);
st.insert(p3);
for(set<Person comparePerson>::iterator it=st.begin();it!=st.end();it++)
{
cout<<"姓名"<<it->name<<"年龄"<<it->age<<endl;
}
map/multimap容器
容器中所有元素都是pair,pair第一个值称为key,起到索引作用,第二个值称为value。所有元素根据key进行排序,map不允许有重复key值,multimap可以重复,都属于关联式容器。
赋值和构造
函数原型:
map<T1,T2> mp; //默认构造
map(const map &mp); //拷贝构造
map& operator=(const map &mp); //重载=
大小和交换
函数原型:
size(); //返回容器大小
empty(); //判断容器是否为空
swap(); //交换容器
插入和删除
函数原型:
insert(elem); //插入一个元素
clear(); //删除所有元素
erase(pos); //删除指定位置元素
erase(begin,end); //删除区间内的元素
erase(key); //删除容器中的值为key的对组
插入方式:
map<int,int> mp;
//1
mp.insert(pair<int,int>(1,10));
//2
mp.insert(make_pair(2,20));
//3
mp.insert(pair<int,int>::value_type(3,30));
//4,不推荐,因为比如查看mp[5],但是容器里没有key为5的对组,就会自己创建一个队组,key为5,value为0
//可以利用[]来访问value
mp[4]=40;
查找和统计
函数原型:
find(key); //查找到则返回该位置迭代器,否则返回end迭代器
count(key); //统计元素为key的个数,对于map容器,结果只有0,1
排序
set容器默认排序是从小到大,可以利用仿函数修改排序规则
//首先定义一个类,用于设置排序规则
class MyCompare{
public:
bool operator()(int v1,int v2)
{
return v1>v2;//降序的时候前面的数大于后面的数
}
};
//在创建的时候把设置规则的类也指定好
map<int,int,MyCompare> mp;
mp.insert(pair<int,int>(1,10));
mp.insert(pair<int,int>(2,20));
mp.insert(pair<int,int>(3,30));
mp.insert(pair<int,int>(4,40));
for(set<int,int,MyCompare>::iterator it=mp.begin();it!=mpend();it++)
{
cout<<it->first<<": "<<it->sceond<<endl;
}
本文详细介绍了C++中的STL容器,包括vector、string、deque、stack、queue、list、set、multiset、map和multimap。内容涵盖构造函数、赋值操作、插入删除、数据存取、排序等核心知识点。

1230

被折叠的 条评论
为什么被折叠?



