C++(STL)

本文详细介绍了C++中的STL容器,包括vector、string、deque、stack、queue、list、set、multiset、map和multimap。内容涵盖构造函数、赋值操作、插入删除、数据存取、排序等核心知识点。

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<intint,MyCompare>::iterator it=mp.begin();it!=mpend();it++)
{
	cout<<it->first<<": "<<it->sceond<<endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值