c++入门学习⑨——STL(万字总结,超级超级详细版)看完这一篇就够了!!!

news2024/11/17 2:24:57

目录

🎄前言

🎄概念

引入

定义

优点

🎄六大组件

容器

算法

迭代器

仿函数

适配器

空间配置器

🎄三大组件

迭代器(iterator)

定义

分类:

正向迭代器:

常量正向迭代器:

反向迭代器:

常量反向迭代器:

用法:

🎄STL常用容器

介绍:

分类

作用

常用容器:

Vector容器

介绍:

构造/初始化

常用迭代器和遍历方法

特殊遍历案例:

赋值

大小、容量

插入删除操作

元素访问和存取方式

vector容器互换操作的扩展使用

vector容器的预留问题

string容器

补充概念

概念

特点

构造

赋值

拼接

查找和替换

字符串比较

存取

插入删除

子串

deque容器

概念:

deque与vector区别:

工作原理:

赋值

大小

插入和删除操作

查找存取

排序

stack容器

构造

赋值

存取

大小

代码示例:

​编辑

queue容器

构造

赋值

存取

大小

代码示例:

list容器

创建

赋值

大小

插入和删除

存取

迭代器

排序

set容器/multiset容器

简介

区别

构造

赋值

大小

插入和删除

统计数据

sort排序规则如何改变

pair对组

两种创建方式:

map容器/multimap容器

简介

本质

优点

区别

构造和赋值

大小

插入和删除

查找

变排序规则

🎄STL函数对象

函数对象

概念:

区别和共性:

谓词

而且分为两类:

内置的函数对象

分类:

算数仿函数

关系仿函数

逻辑仿函数

🎄STL算法

常用算法:

1.遍历算法

for_each

transform

2.查找算法 

find

find_if

adjacent_find

binary_search

count

count_if

3.排序算法

sort

random_shuffle

merge

reverse

4.拷贝和替换函数

copy

replace

replace_if

swap

5.算术生成算法

fill

accumulate

6.集合算法

set_intersection

🎄总结


🎄前言

本篇博客主要介绍有关STL的知识,设计常用容器及常用算法等知识,内容细节会比较多,也比较细,希望对大家有所帮助。(●'◡'●)

文章会不定时更新细节,欢迎继续关注。

🎄概念

引入

复用性,这个是软件界希望达到的一个性能。

而复用性必须建立在某种标准下,

为了建立数据结构和算法的一套标准,而且降低他们的相互胶着的性质,而提升他们的独立性、弹性、交互操作性、因此在这个环境下,STL诞生了。

STL几乎所有代码都是用模板类和模板函数,提高了代码的重用性。

c++标准程序库中隶属于STL的已经超过百分之八十以上。

定义

STL(Standard Template Library)——每个字母分别代表标准、模板、库

STL不是面向对象的编程——而是一种不同的编程模式——通用编程技术

优点

不需要额外安装

高可重用性,高移植性,跨平台性

将数据和操作分离,数据由容器类别加以管理,

程序员不需要直到它的据体实现过程,只需要可以熟练使用即可

🎄六大组件

STL提供了六大组件,彼此之间可以组合套用。

容器、算法、迭代器、仿函数、适配器、空间配置器

容器

各种数据结构,用来存放数据,实现角度来看,STL容器实际上是一种类模板

算法

各种各样的算法,功能模板

迭代器

容器和算法的胶着剂,分为五种类型

每个容器都有自己的迭代器,初学阶段可以把它看为指针

仿函数

行为类似函数,可作为算法的某种策略,从实现角度来看,仿函数是一种重载了operator()的class或者是类模板

适配器

修饰容器或是仿函数或迭代器接口的东西

空间配置器

负责空间的配置和管理,

而其中的前三个组件是STL广义上的分类,主要重点就集中在这三个上

🎄三大组件

 三大组件的关系——容器和算法通过迭代器来进行无缝连接,算法通过迭代器访问容器中的元素

实际上,所谓容器是存储数据的地方,而算法是操作,操作需要对数据进行,这时候需要迭代器来使这两个联系起来

迭代器(iterator)

定义

迭代器可以指向容器中的某个元素,通过迭代器可以指向容器中的元素,通过迭代器可以读写它指向的元素——因此它在某方面很像指针,初学者可以先把它看成指针使用

它是一种广义指针,它是一个可以完成类似指针操作的对象

迭代器是一个接口,指向容器的数据,然后算法通过这个迭代器去实现对容器的操作,相当于一个容器和算法的粘合剂

不同的容器通常有着自己的迭代器,迭代器的类型是一个iterator的typedef类型,作用域为整个类。

分类:

正向迭代器:

容器类名::iterator  迭代器名

常量正向迭代器:

容器类名::const_iterator  迭代器名

反向迭代器:

容器类名::reverse_iterator  迭代器名

常量反向迭代器:

容器类名::const_reverse_iterator  迭代器名

用法:

前面已经说过,它指向某个元素,可以看为指针,那*迭代器名就可以表示迭代器所指的元素了。

而每一个容器都有它自己的迭代器,根据不同迭代器指向的位置的不同,可以进行不同的用途,具体用法在下面容器中介绍——

🎄STL常用容器

介绍:

任何数据结构都是为了实现某种特定算法,STL容器就是将运用最广泛的一些数据结构实现出来,

例如——数组、链表、树、栈、队列、集合、映射表

他们可以根据在容器种的排列特性来分类——

分类

序列式——需要注意数据存储时的数据顺序

每个元素均有固定的位置,除非用删除或是插入改变这个位置,Vector容器,Deque容器,List容器等

关联式——不需要关心其顺序

非线性的树结构,二叉树结构,特点是——在值中选择一个树作为关键字key,起索引作用,Set和Map容器

作用

常用容器:

Vector容器

介绍:
  • vector是将元素置于一个动态数组中加以管理的容器,可以随时添加数值和删除元素,存放内置数据类型
  • vector可以随机存取元素
  • vector尾部添加或移除元素非常快速。但是在中部或头部插入元素或移除元素比较费时

⭐注意:在局部区域中创建vector数组,在堆空间里开——因为栈区比较小,假如放非常长的数组会发生爆栈,因此局部区域不可以开大长度数组,但是可以开大长度vector

包含头文件——#include<vector>

⭐与数组的区别:vector可动态分配

动态分配——vector先开辟一块空间,然后假如需要的空间大于这个开辟的空间了,vector不会在原有空间后面再开辟一块空间,而是在其他地方再找一块空间,然后把原有空间的值给复制到这个新空间,然后插入需要的值,这种方法导致——原有的迭代器将没用了,它们指向的不是这个新的空间,而老的空间已经报废了,因此这个动态内存分配会出现这个问题

vector的迭代器是随机访问的迭代器 

构造/初始化

vector容器采用模板构造

//1.默认构造
vector<类型> 数据名

//示例:
vector<node> a;//定义了一个叫a一维数组,而且数组存储结构体类型数据


//2.带参数的构造
vector<类型> 数据名(n)//n代表这个数组长度为n
vector<类型> 数据名(beg,end)//把beg到end区间里的所有元素赋值给这个,其中区间是左闭右开

//示例:
vector<int> b(n);//定义一个长度为n的数组,初始的默认值都为0,下标从0到n-1
//如果想指定初始化值
vector<int> b(n,1)//初始的默认值都为1了


//3.初始化多个元素
vector<类型> 数据名{数据}//定义一个数组,里面有的数据由定义时的{}里的数据决定


//4.拷贝初始化
vector<int> a(5,0)//定义一个数组,长度为5,初始值都为0
vector<int> b(a);//把a的所有数据都拷贝到b上,前提是所对应的b数组中的类型相同
vector<int> c=a;//c和a一样了


//5.二维构造
vector<int> a[10];//这里是定义一个第一维的长度为10且固定,而第二维可变化的二维数组
vector<vector<int>> b;//第一维第二维均可变
vector<vector<int>> c(n,vector<int>(m,0))//均固定,且初始值都为0

这里一般的都好理解,有一点难度的是嵌套构造——

vector<vector<int>> a

这个是一种嵌套构造方式,其中a它的每一个元素都是整型动态数组。

vector容器嵌套可以使用下标方式访问——前提是必须初始化一维数组的数量

vector<vector<int>>a(3,vector<int>(4,'\0'))拷贝构造函数,区间拷贝构造函数

自定义:vector<vector<int>>(行数,vector<int>())

常用迭代器和遍历方法

数组名称.begin()

返回首元素的迭代器——地址

数组名称.end()

返回最后一个元素的后一个位置的迭代器——地址

数组名称.empty()

判断是否为空,空则返回真,反之返回假

数组名称.push_back()

在尾部插入值

数组名称.pop_back()

删除最后一个值

数组名称.clear()

数组名称.resize()

重新指定大小

数组名称.size()

返回数组的大小

数组名称.erase()

清除数组中的一些元素

补充:STL函数——排序

sort(beg,end).对区间beg到end里的数据从小到大排序

使用反向迭代器降序排序

遍历方法:

1.for循环来遍历

先使用函数,引用传参,在函数里放一个for循环,设置一个迭代器指向数组的开始,让这个迭代器不等于数组的最后,且每次执行都要加一次1.

代码如下:

void bl(vector<int>& a)
{
	for (vector<int>::iterator it = a.begin(); it != a.end(); it++)
	{
		cout << *it << endl;
	}
}

2.遍历算法——算法头文件#include<algorithms>

for_each(v.begin(),v.end(),myprint)

代码示例:

void fun(int i)
{
	cout << i<<" ";
}
vector<int> b;
b.assign(3,10);
bl(b);
for_each(b.begin(), b.end(), fun);

3.利用迭代器

//利用迭代器来遍历
vector<int>::iterator be = a.begin();
vector<int>::iterator en = a.end();
while (be != en)
{
	cout << *be << " ";
	be++;
}cout << endl;
特殊遍历案例:

1.自定义数据类型遍历

2.嵌套式的容器遍历

赋值

vector.assign(beg,end);//将(beg,end)区间中的数据拷贝赋值给本身。注意该区间。
vector.assign(n,elem);//将n个elem拷贝赋值给本身。
vector&operator=(const vector &vec);//重载等号操作符
vector.swap(vec);/将vec与本身的元素互换。

使用示例:

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
//vector.assign(beg,end);//将(beg,end)区间中的数据拷贝赋值给本身。注意该区问。
//vector.assign(n, elem);//将n个elem拷贝赋值给本身。
//vector& operator=(const vector& vec);//重载等号操作符
//vector.swap(vec); / 将vec与本身的元素互换。
void bl(vector<int>& a)
{
	for (vector<int>::iterator it = a.begin(); it != a.end(); it++)
	{
		cout << *it<<" ";
	}
	cout << endl;
}
void fun(int i)
{
	cout << i<<" ";
}
void test1()
{
	int s[5] = { 1,2,3,4,5 };
	vector<int> a;
	a.assign(s,s+4);
	cout << "第一次赋值得出的值为" << endl; 
	bl(a);

	a.assign(2, 10);
	cout << "第二次赋值得出的值为" << endl;
	bl(a);

	vector<int> b;
	b = a;

	bl(b);
	for_each(b.begin(), b.end(), fun);
	cout << endl;

	vector<int> c;
	c.assign(4, 2);

	//交换前的值
	cout << "交换前的值" << endl;
	bl(a);
	bl(c);
	a.swap(c);
	//交换后的值
	cout << "交换后的值" << endl;
	bl(a);
	bl(c);
}

int main() {
	test1();
	return 0;
}

大小、容量

resize()//对容器的大小,进行修改,重新指定大小,如果重新指定的比原来长默认用0填充新的位置,如果重新指定的比原来短超出部分会删除

size()//判断容器大小

capcity()//判断容器容量

empty()//判断容器内是否为空

代码示例:

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
//resize()//对容器的大小,进行修改,重新指定大小,如果重新指定的比原来长,默认用0填充新的位置,如果重新指定的比原来短,超出部分会删除掉
//size()//判断容器大小
//capcity()//判断容器容量
//empty()//判断容器内是否为空
void fun(int i)
{
	cout << i<<" ";
	
}
void test1()
{
	vector<int> a;
	a.assign(5, 3);
	for_each(a.begin(), a.end(),fun);
	cout << endl;

	if (empty(a))
	{
		cout << "容器为空" << endl;
	}
	else {
		cout << "容器不为空" << endl;
		cout << "容器大小为" << a.size() << endl;
		cout << "容器容量为" << a.capacity() << endl;
	}
	a.resize(8);
	cout << "重新制定大小大了" << endl;
	for_each(a.begin(), a.end(), fun);
	cout << endl;
	a.resize(2);
	cout << "重新制定大小小了" << endl;
	for_each(a.begin(), a.end(), fun);
	cout << endl;
}

int main() {
	test1();
	return 0;
}

插入删除操作

push_back(ele); //尾部插入元素ele
pop_back(); //删除最后一个元素
insert(const_iterator pos,ele); //迭代器指向位置pos插入元素ele
insert(const iterator pos,int count,ele);//迭代器指向位置pos插入count个元素ele
erase(const_iterator pos); //删除迭代器指向的元素
erase(const_iterator start, const.iterator end);//删除迭代器从start到end之间的元素
clear(); //删除容器中所有元素

 代码示例:

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
//push_back(ele); //尾部插入元素ele
//pop_back(); //删除最后一个元素
//insert(const_iterator pos, ele); //迭代器指向位置pos插入元素ele
//insert(const iterator pos, int count, ele);//迭代器指向位置pos插入count个元素ele
//erase(const_iterator pos); //删除迭代器指向的元素
//erase(const_iterator start, const.iterator end);//删除迭代器从start到end之间的元素
//clear(); //删除容器中所有元素
void fun(int i)
{
	cout << i<<" ";
	
}
void test1()
{
	vector<int> a;
	a.push_back(1);
	a.push_back(2);
	a.push_back(3);
	a.push_back(4);
	a.push_back(5);
	//12345,不删除元素的情况下的原始数据
	cout << "不删除元素的情况下的原始数据" << endl;
	for_each(a.begin(), a.end(), fun);
	cout << endl;
	//删除了最后一个元素的数据
	cout << "删除了最后一个元素的数据" << endl;
	a.pop_back();
	for_each(a.begin(), a.end(), fun);
	cout << endl;

	//插入了一个0后的数据
	cout << "插入了一个0后的数据" << endl;
	a.insert(a.begin(), 0);
	for_each(a.begin(), a.end(), fun);
	cout << endl;

	//又插入了两个0后的数据
	cout << "又插入了两个0后的数据" << endl;
	a.insert(a.begin(), 2,0);
	for_each(a.begin(), a.end(), fun);
	cout << endl;

	//删除了开始迭代器指向的位置
	cout << "删除了开始迭代器指向的位置" << endl;
	a.erase(a.begin());
	for_each(a.begin(), a.end(), fun);
	cout << endl;
	
	//删除了开始迭代器到迭代器往后的两位之间的数据
	cout << "删除了开始迭代器到迭代器往后的两位之间的数据" << endl;
	a.erase(a.begin(), a.begin() + 2);
	for_each(a.begin(), a.end(), fun);
	cout << endl;
}

int main() {
	test1();
	return 0;
}

元素访问和存取方式

at(iht idx); //返回索引idx所指的数据
operator[ ]; //返回索引idx所指的数据
front(); //返回容器中第一个数据元素
back(); //返回容器中最后一个数据元素

代码示例:

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
//at(iht idx); //返回索引idx所指的数据
//operator[ ]; //返回索引idx所指的数据
//front(); //返回容器中第一个数据元素
//back(); //返回容器中最后一个数据元素
void fun(int i)
{
	cout << i<<" ";
	
}
void test1()
{
	vector<int> a;
	a.push_back(1);
	a.push_back(2);
	a.push_back(3);
	a.push_back(4);
	a.push_back(5);
	cout << "a的第三个数据" << a.at(2) << endl;
	cout << "a的第三个数据" << a[2] << endl;
	cout << "a的第一个数据元素" << a.front() << endl;
	cout << "a的最后一个数据元素" << a.back() << endl;
}

int main() {
	test1();
	return 0;
}

 

vector容器互换操作的扩展使用

前面已经知道了交换是用swap函数来完成的,而这个swap函数不止可以交换两个容器的数据,还可以进行收缩内存——

这里先看一段代码:

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
//swap收缩内存
void fun(int i)
{
	cout << i<<" ";
	
}
void test1()
{
	vector<int> a;
	a.push_back(1);
	a.push_back(2);
	a.push_back(3);
	a.push_back(4);
	a.push_back(5);
	//重新指定内存后的大小和容量
	cout << "重新指定内存后的大小和容量" << endl;
	a.resize(100);
	cout << a.size() << endl;
	cout << a.capacity() << endl;
	//又重新指定小的内存后的大小和容量
	cout << "又重新指定小的内存后的大小和容量" << endl;
	a.resize(3);
	cout << a.size() << endl;
	cout << a.capacity() << endl;

}

int main() {
	test1();
	return 0;
}

指定两次内存后,容器的大小倒是变了,但是容量没变,这会造成很大的浪费,很不好,所以怎么才能把容量也缩小呢?——往下看吧🤭

先看这里代码怎么写的,然后再讲为何这样写:

//利用swap收缩容量后
cout << "利用swap收缩容量后" << endl;
vector<int>(a).swap(a);
cout << a.size() << endl;
cout << a.capacity() << endl;

 

这时候就实现了一个收缩内存的效果,但为什么要这样写?为什么这样写可以达到这个效果呢?

且听下面讲解——

 1.首先这个vector<int>(a)是个匿名对象,它有一个特征就是——匿名对象执行完后编译器会回收空间,所在的空间被释放

如下图详解:

vector容器的预留问题

reserve预留空间

因为vector的特殊性质——它动态开辟内存,如果空间不够,它要在另一块区域开辟足够内存,然后把之前的空间里的数给复制过来,这样导致之前的迭代器都不能用了,因此这里提供一个功能可以提前去开辟足够的空间——👇

string容器

补充概念

const char*

这个是代表指针指向的东西不可以通过指针来修改了,但是指针本身的地址可以改变,但可以间接不通过指针来修改指向的内容

char const*

等价于const char*

char*const

指针指向的东西定了,不可以指向其他了,表明指针的指向不可改变

const char

c语言中常用的字符数据类型

⭐注:指针改为引用——用法一样

概念

~string容器其实和c语言中的char很像,而string是c++风格的字符串,而string本质上是一个类

特点

string是一个类,类内部封装了char*,管理这个字符串,是一个char*型的容器

string类内部封装了很多成员方法

string管理char*所分配的内存

构造

string(); //创建一个空的字符串例如:string  str;
string(const char*s); //使用字符串s初始化
string(const string& str); //使用一个string对象初始化另一个string对象
string(int n, char c); //使用n个字符c初始化

代码示例:

#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
//string(); //创建一个空的字符串例如:string  str;
//string(const char* s); //使用字符串s初始化
//string(const string& str); //使用一个string对象初始化另一个string对象
//string(int n, char c); //使用n个字符c初始化
void test1()
{
	string a="hehe";
	string b(a);
	string c("哈哈");
	string d(3, 'a');
	cout << a << endl;
	cout << b << endl;
	cout << c << endl;
	cout << d << endl;
}

int main() {
	test1();
	return 0;
}

赋值

string& operator=(const char* s); //char*类型字符串 赋值给当前的字符串
string& operator=(const string &s);//把字符串s赋给当前的字符串
string& operator=(char 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个字符e赋给当前字符串

代码示例:

#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
//string& operator=(const char* s); //char*类型字符串 赋值给当前的字符串
//string& operator=(const string& s);//把字符串s赋给当前的字符串
//string& operator=(char 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个字符e赋给当前字符串
void test1()
{
	string a="heha";
	string b=a;
	cout << a << endl;//heha
	cout << b << endl;//heha
	string c;
	const char* s = "黑菜钟";
	c.assign(s);
	cout << c << endl;//黑菜钟
	c.assign(a,2);
	cout << c << endl;//he
	c.assign(b);
	cout << c << endl;//heha
	c.assign(3, 'h');
	cout << c << endl;//hhh
	
	
	
}

int main() {
	test1();
	return 0;
}

这个需要注意有的是传入const char*类型的,有的是传入string字符串类型的😉

拼接

string& operator+=(const char* str), //重载+=操作符
string& operator+=(const char c); //重载+=操作符
string& operator+=(const string& str); //重载+=操作符
string& append(const char*s); //把字符串s连接到当前字符串结尾
string& append(const char*s,int n); //把字符串s的前n个字符连接到当前字符串结
string& append(const string &s); //同operator+(const string& str)
string& append(const string &s, int pos,int n);/字符串s中从pos开始的n个字符连接到字符串结尾

代码示例:

#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
//string& operator+=(const char* str), //重载+=操作符
//string& operator+=(const char c); //重载+=操作符
//string& operator+=(const string& str); //重载+=操作符
//string& append(const char* s); //把字符串s连接到当前字符串结尾
//string& append(const char* s, int n); //把字符串s的前n个字符连接到当前字符串结
//string& append(const string& s); //同operator+=(const string& str)
//string& append(const string& s, int pos, int n); / 字符串s中从pos开始的n个字符连接到字符串
void test1()
{
	string a="我";
	string b = "辣条";
	a += ("吃");
	a += (b);
	a += ("a");
	cout << a << endl;

	string c = "abc";
	string d = "k";
	c.append("de");
	c.append("fghee", 3);
	c.append(d);
	cout << c << endl;

}

int main() {
	test1();
	return 0;
}

查找和替换

int find(const string& str, int pos) const; //查找str第一次出现位置,从pos开始查找
int find(const char* s, int pos )const; //查找s第一次出现位置,从pos开始查找
int find(const char* s, int pos, int n) const; //从pos位置查找s的前个字符第一次位置
int find(const char c, int pos) const; //查找字符c第一次出现位置
int rfind(const string& str, int pos) const; //查找str最后一次位置,从pos开始查找
int rfind(const char* s, int pos) const; //查找s最后一次出现位置,从pos开始查找
int rfind(const char* s, int pos, int n) const; //从pos查找s的前n个字符最后一次位置
int rfind(const char c, int pos) const; //查找字符c最后一次出现位置
string& replace(int pos, int n, const string& str); //替换从pos开始n个字符为字符串str
string& replace(int pos, int n, const char* s); //替换从pos开始的n个字符为字符串s

 注意:⭐rfind从右往左查找 find从左往右查找

代码案例:

#include<iostream>
#include<string>

using namespace std;
//int find(const string& str, int pos) const; //查找str第一次出现位置,从pos开始查找
//int find(const char* s, int pos )const; //查找s第一次出现位置,从pos开始查找
//int find(const char* s, int pos, int n) const; //从pos位置查找s的前个字符第一次位置
//int find(const char c, int pos) const; //查找字符c第一次出现位置
//int rfind(const string& str, int pos) const; //查找str最后一次位置,从pos开始查找
//int rfind(const char* s, int pos) const; //查找s最后一次出现位置,从pos开始查找
//int rfind(const char* s, int pos, int n) const; //从pos查找s的前n个字符最后一次位置
//int rfind(const char c, int pos) const; //查找字符c最后一次出现位置
//string& replace(int pos, int n, const string& str); //替换从pos开始n个字符为字符串str
//string& replace(int pos, int n, const char* s); //替换从pos开始的n个字符为字符串s
void test1()
{
	string a = "abcdefgde";
	int pos = a.find("de", 0);//3
	cout << pos << endl;
	pos = a.find("cf");//-1=>未找到
	cout << pos << endl;

	pos = a.rfind("de");//7
	cout << pos << endl;

	//替换
	string b = "abcdefg";
	b.replace(1, 3, "1234");//a1234efg
	cout << b << endl;
}


int main() {
	test1();
	return 0;
}

字符串比较

字符串比较是按字符的ASCII码进行对比
=则返回0
>则返回1
<则返回-1

函数原型——

int compare(const string &s) const; //与字符串s比较
int compare(const char *s) const; //与字符串s比较

代码案例:

#include<iostream>
#include<string>
using namespace std;
//int compare(const string& s) const; //与字符串s比较
//int compare(const char* s) const; //与字符串s比较
void test1()
{
	string a = "abc";
	string b = "a";
	int f = a.compare(b);
	cout << f << endl;//1

	f = a.compare("abcd");
	cout << f << endl;//-1

	f = a.compare("abc");//0
	cout << f << endl;
}


int main() {
	test1();
	return 0;
}

存取

存取方式有两种:

1.char& operator[](int n);

2.char &at(int a);

 代码示例:

#include<iostream>
#include<string>
using namespace std;
//存取
// 1.char& operator[](int n);
//2.char& at(int a);
void test1()
{
	string a = "abcd";

	cout << a.at(0) << endl;//a

	cout << a[2]<<endl;//c
}

int main() {
	test1();
	return 0;
}

插入删除

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 npos); //删除从pos开始的n个字符

代码案例:

#include<iostream>
#include<string>
using namespace std;
//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 npos); //删除从pos开始的n个字符
void test1()
{
	string a = "abcd";
	string b = "gef";

	a.insert(2, "111");
	cout << a << endl;

	a.insert(7, b);
	cout << a << endl;

	a.insert(10, 2, 'a');
	cout << a << endl;

	a.erase(2, 4);
	cout << a << endl;

	string c = a.substr(0, 6);
	cout << c << endl;
}

int main() {
	test1();
	return 0;
}

子串

从字符串中获取想要的子串

函数原型:
string substr(int pos o,int npos) const; //返回由pos开始的n个字符组成的字符串

代码案例:

#include<iostream>
#include<string>
using namespace std;
//子串
void test1()
{
	string a = "abcdef";
	string c = a.substr(0,4);
	cout << c << endl;
}

int main() {
	test1();
	return 0;
}

deque容器

概念:

区别——vector为单端数组,头插不好插,而这个头插比较方便,vector的访问遍历比较快,因为它是连续的空间

deque与vector区别:

vector对于头部的插入删除效率低,数据量越大,效率越低
deque相对而言,对头部的插入删除速度回比vector快
vector访问元素时的速度会比deque快,这和两者内部实现有关

工作原理:

赋值

deque&operator=(const deque &a); //重载等号=操作符
assign(beg,end); //将【beg,end】区间中的数据拷贝赋值给本身,注意这个不可以是数组,要是迭代器
assign(n,elem); //将n个elem拷贝赋值给本身

代码示例:

#include<iostream>
#include<deque>
using namespace std;
//deque&operator=(const deque &a); //重载等号=操作符
//assign(beg, end); //将【beg,end】区间中的数据拷贝赋值给本身,注意这个不可以是数组,要是迭代器
//assign(n, elem); //将n个elem拷贝赋值给本身
void print(deque<int>& a)
{
	for (deque<int>::iterator it = a.begin(); it != a.end(); it++)
	{
		cout << *it;
	}cout << endl;
}
void test1()
{
	deque <int>a;
	deque <int>b;
	deque<int>c;
	c.push_back(1);
	c.push_back(2);
	c.push_back(3);
	c.push_back(4);
	c.push_back(5);
	a.assign(3, 8);
	print(a);
	a.assign(c.begin(), c.end());
	print(a);
	b = a;
	print(b);
}

int main() {
	test1();
	return 0;
}

大小

deque.empty(); //判断容器是否为空
deque.size(); //返回容器中元素的个数
deque.resize(num); //重新指定容器的长度为num,若容器变长,则以默认值填充新位置。
//如果容器变短,则末尾超出容器长度的元素被删除。
deque.resize(num,elem); //重新指定容器的长度为num,若容器变长,则以elem值填充新位置。
//如果容器变短,则末尾超出容器长度的元素被删除。

代码示例:

#include<iostream>
#include<deque>
using namespace std;
//deque.empty(); //判断容器是否为空
//deque.size(); //返回容器中元素的个数
//deque.resize(num); //重新指定容器的长度为num,若容器变长,则以默认值填充新位置。
如果容器变短,则末尾超出容器长度的元素被删除。
//deque.resize(num, elem); //重新指定容器的长度为num,若容器变长,则以elem值填充新位置。
如果容器变短,则末尾超出容器长度的元素被删除。
void print(const deque<int>& a)
{
	for (deque<int>::const_iterator it = a.begin(); it != a.end(); it++)
	{
		cout << *it;
	}cout << endl;
}
void test1()
{
	deque <int>a;
	a.push_back(1);
	a.push_back(2);
	a.push_back(3);
	a.push_back(4);
	a.push_back(5);
	if (a.empty())
	{
		cout << "为空" << endl;
	}else
	{
		cout << a.size() << endl;
	}
	a.resize(3);
	print(a);
	a.resize(8);
	print(a);
}

int main() {
	test1();
	return 0;
}

插入和删除操作

两端插入操作:
push back(elem); //在容器尾部添加一个数据
push_front(elem); //在容器头部插入一个数据
pop_back(); //删除容器最后一个数据
pop_front(); //删除容器第一个数据
指定位置操作:
insert(pos,elem); //在pos位置插入一个elem元素的拷贝,返回新数据的位置。
insert(pos,n,elem); //在pos位置插入n个elem数据,无返回值。
insert(pos,beg,end); //在pos位置插入【beg,end)区间的数据,v无返回值。
clear(); //清空容器的所有数据
erase(beg,end); //删除【beg,end)区间的数据,返回下一个数据的位置。
erase(pos); /删除pos位置的数据,返回下一个数据的位置。

代码示例:

#include<iostream>
#include<deque>
using namespace std;
//两端插入操作:
//push back(elem); //在容器尾部添加一个数据
//push_front(elem); //在容器头部插入一个数据
//pop_back(); //删除容器最后一个数据
//pop_front(); //删除容器第一个数据
//指定位置操作:
//insert(pos, elem); //在pos位置插入一个elem元素的拷贝,返回新数据的位置。注意pos位置为迭代器
//insert(pos, n, elem); //在pos位置插入n个elem数据,无返回值。
//insert(pos, beg, end); //在pos位置插入【beg,end)区间的数据,无返回值。
//clear(); //清空容器的所有数据
//erase(beg, end); //删除【beg,end)区间的数据,返回下一个数据的位置。
//erase(pos); / 删除pos位置的数据,返回下一个数据的位置。
void print(const deque<int>& a)
{
	for (deque<int>::const_iterator it = a.begin(); it != a.end(); it++)
	{
		cout << *it;
	}cout << endl;
}
void test1()
{
	deque <int>a;
	int i = 1;
	for (; i < 6; i++)
	{
		a.push_back(i);
	}
	print(a);
	a.push_front(0);
	print(a);
	a.pop_back();
	print(a);
	a.pop_front();
	print(a);
	

	deque<int> b;
	b.assign(3, 4);
	b.insert(b.begin(), 2);
	print(b);
	b.insert(b.begin(), 2,0);
	print(b);
	b.insert(b.end(), a.begin(), a.end());
	print(b);

	b.clear();
	print(b);
	a.erase(a.begin());
	print(a);
}

int main() {
	test1();
	return 0;
}

查找存取

at(int idx); //返回索引idx所指的数据
operator[]; /返回索引idx所指的数据
front(); //返回容器中第一个数据元素
back(); //返回容器中最后一个数据元素

代码示例:

#include<iostream>
#include<deque>
using namespace std;
//at(int idx); //返回索引idx所指的数据
//operator[]; / 返回索引idx所指的数据
//front(); //返回容器中第一个数据元素
//back(); //返回容器中最后一个数据元素
void print(const deque<int>& a)
{
	for (deque<int>::const_iterator it = a.begin(); it != a.end(); it++)
	{
		cout << *it;
	}cout << endl;
}
void test1()
{
	deque <int>a;
	int i = 1;
	for (; i < 6; i++)
	{
		a.push_back(i);
	}
	cout << a.at(0) << endl;
	cout << a[0] << endl;
	cout << a.front() << endl;
	cout << a.back() << endl;
}

int main() {
	test1();
	return 0;
}

排序

利用算法实现对deque容器进行排序——标准算法头文件,algorithm
sort(iterator beg,iterator end) //对beg和end区间内元素进行排序

这个排序为升序排列,但是也可以通过一些操作完成降序排列,后面再讲

代码示例:

#include<iostream>
#include<deque>
#include<algorithm>
using namespace std;
//利用算法实现对deque容器进行排序——标准算法头文件,algorithm
//sort(iterator beg, iterator end) //对beg和end区间内元素进行排序
//
//这个排序为升序排列,但是也可以通过一些操作完成降序排列,后面再讲
void print(const deque<int>& a)
{
	for (deque<int>::const_iterator it = a.begin(); it != a.end(); it++)
	{
		cout << *it;
	}cout << endl;
}
void test1()
{
	deque <int>a;
	a.push_back(4);
	a.push_back(3);
	a.push_back(6);
	a.push_back(1);
	a.push_back(2);
	a.push_back(5);
	sort(a.begin(), a.end());
	print(a);
}

int main() {
	test1();
	return 0;
}

stack容器

stack是一种先进后出的数据结构,只有一个出口,也就是我们俗说的栈

栈不允许有遍历行为,只有顶部元素可以使用

构造

构造函数:
stack<t> stk;采用模板类实现,stack对象的默认构造形式
stack(const stack &stk);//拷贝构造函数

赋值

赋值操作:
stack&operator=(const stack &stk); //重载等号操作符

存取

数据存取:
push(elem); //向栈顶添加元素
基本接口
pop(); //从栈顶移除第一个元素
top(); //返回栈顶元素

大小

大小操作:
empty(); //判断堆栈是否为空
size(); //返回栈的大小

代码示例:
#include<iostream>
#include<stack>
#include<algorithm>
using namespace std;
//stack<t> stk; 采用模板类实现,stack对象的默认构造形式
//stack(const stack& stk); l / 拷贝构造函数
//赋值操作:
//stack & operator=(const stack & stk); //重载等号操作符
//数据存取:
//push(elem); //向栈顶添加元素
//基本接口
//pop();  / 从栈顶移除第一个元素
//top(); //返回栈顶元素
//大小操作:
//empty(); //判断堆栈是否为空
//size(); // 返回栈的大小
void test1()
{
	stack <int>a;//没有遍历行为
	a.push(1);
	a.push(2);
	a.push(3);
	a.push(4);
	stack<int> b;
	b = a;
	b.pop();
	cout << "a的栈顶元素为" << a.top() << endl;
	cout << "b的栈顶元素为" << b.top() << endl;
	if (a.empty())
	{
		cout << "为空" << endl;

	}
	else {
		cout << "a的大小为:" << a.size() << endl;
	}
}

int main() {
	test1();
	return 0;
}

queue容器

queue是一种先进先出的数据结构,有两个出口。

队列容器允许从一端新增元素,从另一端移除元素
队列中只有队头和队尾才可以被外界使用,因此队列不允许有遍历行为
队列中进数据称为--入队 push

构造

构造函数:
queue<t> que; //queue采用模板类实现,queue对象的默认构造形式
queue(const queue &que); //拷贝构造函数

赋值

赋值操作:
queue& operator=(const queue &que); 1/重载等号操作符

存取

数据存取:
push(elem); //往队尾添加元素
pop(); //从队头移除第一个元素
back(); //返回最后一个元素
front(); //返回第一个元素

大小

大小操作:
empty(); /判断堆栈是否为空size(): /返回栈的大小

代码示例:
#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;
//构造函数:
//queue<t>que; //queue采用模板类实现,queue对象的默认构造形式
//queue(const queue& que); //拷贝构造函数
//赋值操作:
//queue& operator=(const queue& que); // 重载等号操作符
//数据存取:
//push(elem); // 往队尾添加元素
//pop(); //从队头移除第一个元素
//back(); //返回最后一个元素
//front(); //返回第一个元素
//大小操作:
//empty(); / 判断堆栈是否为空
//size() : / 返回栈的大小
void test1()
{
	queue<int> a;
	a.push(5);
	a.push(4);
	a.push(3);
	a.push(2);
	a.push(1);
	a.pop();
	cout << a.back() << endl;
	cout << a.front() << endl;
	if (a.empty()) {
		cout << "为空" << endl;
	}
	else {
		cout << "大小为" << a.size() << endl;
	}
}

int main() {
	test1();
	return 0;
}

list容器

将数据链式存储起来

优点:
可以对任意位素进行快速插入或删除元素

缺点:
容器遍历速度,没有数组快
占用空间比数组大

创建

list<T>lis: //list采用采用模板类实现,对象的默认构造形式:
list(beg.end): /构造函数(beg.,end)//区间中的元素拷贝给本身。
list(n,elem): //构造函数将n个elem拷贝给本身。
list(const list&lis). //拷贝构造函数。

代码示例:

#include<iostream>
#include<list>
#include<algorithm>
using namespace std;
//list<T>lis: //list采用采用模板类实现,对象的默认构造形式:
//list(beg.end) : / 构造函数(beg., end)//区间中的元素拷贝给本身。
//list(n, elem) : //构造函数将n个elem拷贝给本身。
//	list(const list & lis). //拷贝构造函数。
void pri(list<int>& a)
{
	for (list<int>::iterator it = a.begin(); it != a.end(); it++)
	{
		cout << *it;
	}cout << endl;
}
void test1()
{
	list <int> a;
	a.push_back(1);
	a.push_back(2);
	a.push_back(3);
	a.push_back(4);
	a.push_back(5);
	list<int>b(a.begin(), a.end());
	list<int>c(5, 3);
	list<int>d = a;
	pri(a);
	pri(b);
	pri(c);
	pri(d);
}

int main() {
	test1();
	return 0;
}

赋值

assign(beg,end): /将【beg,end)区间中的数据拷贝赋值给本身。
assign(n,elem): //将n个elem拷贝赋值给本身。
list&operator(const list&lst) //重载等号操作符
swap(st) 将st与本身的元素互换。

代码案例:

#include<iostream>
#include<list>
#include<algorithm>
using namespace std;
//assign(beg, end) : / 将【beg, end)区间中的数据拷贝赋值给本身。
//assign(n, elem) : //将n个elem拷贝赋值给本身。
//list & operator(const list& lst) //重载等号操作符
//swap(st) 将st与本身的元素互换。
void pri(list<int>& a)
{
	for (list<int>::iterator it = a.begin(); it != a.end(); it++)
	{
		cout << *it;
	}cout << endl;
}
void test1()
{
	list<int> a;
	a.assign(5, 3);
	pri(a);
	list <int> b;
	b = a;
	pri(b);

	list<int> c;
	int i = 0;
	for (;i < 5; i++)
	{
		c.push_back(i);
	}

	pri(c);

	a.assign(c.begin(),c.end());
	pri(a);
}

int main() {
	test1();
	return 0;
}

大小

size(): //返回容器中元素的个数
empty(): /判断容器是否为空
resize(num) /重新指定容器的长度为mnum,若容器变长,以默认值填充新位置
/如果容器变短,见末尾超出容器长度的元素被删除。
resize(num,elem), /重新指定容器的长度为mum,若容器变长,以elem值填充新位置,
/如果容器变短,则末尾超出容器长度的元素被删除。

代码案例:

#include<iostream>
#include<list>
#include<algorithm>
using namespace std;
//size() : //返回容器中元素的个数
//	empty() : / 判断容器是否为空
//	resize(num) / 重新指定容器的长度为mnum, 若容器变长,以默认值填充新位置
//	/ 如果容器变短,见末尾超出容器长度的元素被删除。
//	resize(num, elem), / 重新指定容器的长度为mum, 若容器变长,以elem值填充新位置,
//	/ 如果容器变短,则末尾超出容器长度的元素被删除。
void pri(list<int>& a)
{
	for (list<int>::iterator it = a.begin(); it != a.end(); it++)
	{
		cout << *it;
	}cout << endl;
}
void test1()
{
	list<int> a;
	a.assign(5, 3);
	pri(a);
	if (a.empty())
	{
		cout << "为空" << endl;
	}
	else
	{
		cout << "a的大小为" << a.size() << endl;
	}

	a.resize(3);
	pri(a);

	a.resize(5,3);
	pri(a);

}

int main() {
	test1();
	return 0;
}

插入和删除

push_back(elem);//在容器尾部加入一个元素。

pop_back();//删除容器中最后一个元素。

push_front(elem);//在容器开头插入一个元素。

pop_front();//从容器开头移除第一个元素
insert(pos,elem);//在pos位置插elem元素的拷贝,返回新数据的位置。

insert(pos,n,elem);//在poS位置插入n个elem数据,无返回值。

insert(pos,beg,end);//在pos位置插入[beg,end)区间的数据,无返回值。
clear();//移除容器的所有数据
erase(beg,end);//删除[beg,end)区间的数据,返回下一个数据的位置

erase(pos);//删除pos位置的数据,返回下一个数据的位置,

remove(elem);//删除容器中所有与elem值匹配的元素。

注意:这个insert里的pos函数不是直接的数字,而是迭代器

代码案例: 

#include<iostream>
#include<list>
#include<algorithm>
using namespace std;
//push_back(elem);//在容器尾部加入一个元素。
//pop_back();//删除容器中最后一个元素。
//push_front(elem);//在容器开头插入一个元素。
//pop_front();//从容器开头移除第一个元素
//insert(pos, elem);//在pos位置插elem元素的拷贝,返回新数据的位置。
//insert(pos, n, elem);//在poS位置插入n个elem数据,无返回值。
//insert(pos, beg, end);//在pos位置插入[beg,end)区间的数据,无返回值。
//clear();//移除容器的所有数据
//erase(beg, end);//删除[beg,end)区间的数据,返回下一个数据的位置
//erase(pos);//删除pos位置的数据,返回下一个数据的位置,
//remove(elem);//删除容器中所有与elem值匹配的元素。
void pri(list<int>& a)
{
	for (list<int>::iterator it = a.begin(); it != a.end(); it++)
	{
		cout << *it;
	}cout << endl;
}
void test1()
{
	list<int> a;
	a.push_back(1);
	a.push_back(2);
	a.push_back(3);
	a.push_back(4);
	a.push_back(5);
	a.push_back(2);
	pri(a);//123452
	a.pop_back();
	pri(a);//12345

	list<int> b;
	b.assign(5, 1);
	a.insert(a.begin(),1);
	pri(a);//112345
	a.insert(a.begin(), 3, 0);
	pri(a);//000112345
	a.insert(a.end(), b.begin(), b.end());
	pri(a);//00011234511111

	a.erase(a.begin());
	pri(a);//0011234511111
	a.remove(1);
	pri(a);//002345
}

int main() {
	test1();
	return 0;
}

存取

对list容器中数据进行存取
函数原型:
front(): //返回第一个元素。
back(): //返回最后一个元素。

代码案例:

#include<iostream>
#include<list>
#include<algorithm>
using namespace std;
//front() : //返回第一个元素。
//back() : //返回最后一个元素。
void pri(list<int>& a)
{
	for (list<int>::iterator it = a.begin(); it != a.end(); it++)
	{
		cout << *it;
	}cout << endl;
}
void test1()
{
	list<int> a;
	a.push_back(1);
	a.push_back(2);
	a.push_back(3);
	a.push_back(4);
	a.push_back(5);
	a.push_back(2);
	cout << "a的最后一个元素为" << a.back()<<endl;
	cout << "a的第一个元素为" << a.front() << endl;
}

int main() {
	test1();
	return 0;
}

迭代器

迭代器是不支持随机访问的

排序

reverse() /反转链表
sort(): //链表排序

代码示例;

#include<iostream>
#include<list>
#include<algorithm>
using namespace std;
//reverse() / 反转链表
//sort() : //链表排序
void pri(list<int>& a)
{
	for (list<int>::iterator it = a.begin(); it != a.end(); it++)
	{
		cout << *it;
	}cout << endl;
}
void test1()
{
	list<int> a;
	a.push_back(1);
	a.push_back(2);
	a.push_back(3);
	a.push_back(4);
	a.push_back(5);
	a.reverse();
	pri(a);

	list<int> b;
	b.push_back(3);
	b.push_back(4);
	b.push_back(6);
	b.push_back(1);
	b.sort();
	pri(b);
	
}

int main() {
	test1();
	return 0;
}

set容器/multiset容器

简介

所有元素都会在插入时自动被排序
本质:
setmultset属于关联式容器,底层结构是用二叉树实现。

区别

set和multiset区别:
set不许容器中有重复的元素
multiset允许容器中有重复的元素

因为

set插入数据的同时会返回插入结果,表示插入是否成功
multiset不会检测数据,因此可以插入重复数据

示例:

#include<iostream>
#include<set>
#include<algorithm>
using namespace std;
void pri(set<int>& a)
{
	for (set<int>::iterator it = a.begin(); it != a.end(); it++)
	{
		cout << *it;
	}cout << endl;
}

void pri2(multiset<int>& a)
{
	for (multiset<int>::iterator it = a.begin(); it != a.end(); it++)
	{
		cout << *it;
	}cout << endl;
} 

void test1()
{
	set<int> a;
	a.insert(1);
	a.insert(2);
	a.insert(3);
	a.insert(4);
	pri(a);
	multiset<int> b;
	b.insert(1);
	b.insert(1);
	b.insert(1);
	b.insert(1);
	b.insert(1);
	pri2(b);
}

int main() {
	test1();
	return 0;
}

构造

构造:
set<t>st: /默认构造函数:
set(const set&st): /拷贝构造函数
代码示例:

#include<iostream>
#include<set>
#include<algorithm>
using namespace std;
//构造:
//set<t>st: / 默认构造函数:
//set(const set & st) : / 拷贝构造函数
void pri(set<int>& a)
{
	for (set<int>::iterator it = a.begin(); it != a.end(); it++)
	{
		cout << *it;
	}cout << endl;
}

void test1()
{
	set<int> a;
	a.insert(a.begin(), 1);
	pri(a);
	set<int> b(a);
	pri(b);
}

int main() {
	test1();
	return 0;
}

赋值

赋值:
set&operator=(const set&st) 重载等号操作符

代码示例:

#include<iostream>
#include<set>
#include<algorithm>
using namespace std;
//赋值
void pri(set<int>& a)
{
	for (set<int>::iterator it = a.begin(); it != a.end(); it++)
	{
		cout << *it;
	}cout << endl;
}

void test1()
{
	set<int> a;
	a.insert(a.begin(), 1);
	pri(a);
	set<int> b;
	b = a;
	pri(b);
}

int main() {
	test1();
	return 0;
}

大小

size(): //返回容器中元素的数目
empty(): //判断容器是否为空
swap(st): //交换两个集合容器

代码示例:

#include<iostream>
#include<set>
#include<algorithm>
using namespace std;
//size() : //返回容器中元素的数目
//	empty() : //判断容器是否为空
//	swap(st) : //交换两个集合容器
void pri(set<int>& a)
{
	for (set<int>::iterator it = a.begin(); it != a.end(); it++)
	{
		cout << *it;
	}cout << endl;
}

void test1()
{
	set<int> a;
	a.insert(a.begin(), 1);
	
	if (a.empty()) {
		cout << "a为空" << endl;
	}
	else {
		cout << a.size() << endl;
	}

	set<int> b;
	b.insert(b.begin(), 2);
	cout << "交换前" << endl;
	pri(a);
	pri(b);
	b.swap(a);
	cout << "交换后" << endl;
	pri(a);
	pri(b);
}

int main() {
	test1();
	return 0;
}

插入和删除

insert(elem): 在容器中插入元素。
clear(): //清除所有元素
erase(pos): /删除pos送代器所指的元素,返回下一个元素的法代器。
erase(beg.end): /除区间beg.end的所有元素,返回下一个元素的送代器。
erase(elem): //删除容器中值为elem的元素。

代码示例:

#include<iostream>
#include<set>
#include<algorithm>
using namespace std;
//insert(elem): 在容器中插入元素。
//clear() : //清除所有元素
//erase(pos) : / 删除pos送代器所指的元素,返回下一个元素的法代器。
//erase(beg,end) : / 除区间beg.end的所有元素,返回下一个元素的送代器。
//erase(elem) : //删除容器中值为elem的元素。
void pri(set<int>& a)
{
	for (set<int>::iterator it = a.begin(); it != a.end(); it++)
	{
		cout << *it;
	}cout << endl;
}

void test1()
{
	set<int> a;
	a.insert(1);
	a.insert(2);
	a.insert(3);
	a.insert(4);
	pri(a);
	set<int> b = a;
	a.clear();
	pri(b);
	pri(a);
	b.erase(2);
	pri(b);
}

int main() {
	test1();
	return 0;
}

统计数据

find(key);

//查找key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end();
count(key); //统计key的元素个数

count由于不可以出现重复数据,则返回要么0或者1

#include<iostream>
#include<set>
#include<algorithm>
using namespace std;
// find(key);
//查找key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end();
//count(key); //统计key的元素个数
void pri(set<int>& a)
{
	for (set<int>::iterator it = a.begin(); it != a.end(); it++)
	{
		cout << *it;
	}cout << endl;
}

void test1()
{
	set<int> a;
	a.insert(1);
	a.insert(2);
	a.insert(3);
	a.insert(4);
	int c=a.count(2);
	cout << c << endl;//1

	if (a.find(2) != a.end())
	{
		cout << "2存在" << endl;
	}
	else
	{
		cout << "2不存在" << endl;
	}
}

int main() {
	test1();
	return 0;
}

sort排序规则如何改变

对于函数sort而言,它一般只会把容器排序成升序的,那么怎么实现将容器排序成降序。

——用仿函数

仿函数的概念到下面讲解stl的函数对象时在细细讲解,这里你只需要知道,这是通过仿函数来实现的。

构建一个类,类里有一个重载函数调用的函数

class Mycompare
{
public:
    bool operator()(int a,int b){
        return a>b;
    }
};

在写sort时,把这个类的类名写在最后一个,也就是第三个参数上, 这样就可以把sort排序变为降序排列了。

pair对组

成对出现的数据,利用对组可以返回两个数据

两种创建方式:

pair<type,type>p(value1,value2);
pair<type, type> p= make_pair( value1, value2);

返回两个数据——用队组

调用用.first和.second

代码示例:

#include<iostream>
#include<string>
#include<stdlib.h>
using namespace std;


void test2()
{
	pair<string, int>a("小红",14);
	cout << a.first << a.second << endl;

	pair<string, int>b = make_pair("小寒", 23);
	cout << b.first << b.second << endl;
}

int main() {
	test2();
	system("pause");
	return 0;
}

map容器/multimap容器

简介

简介:
map中所有元素都是pair对组
pair中第一个元素为key(键值),起到索引作用,第二个元素为value(实值)
所有元素都会根据元素的键值自动排序

本质

本质:
map/multimap属于关联式容器,底层结构是用二叉树实现。

优点

优点:
可以根据key值快速找到value值

区别

map和multimap区别:
map不允许容器中有重复key值元素
multimap允许容器中有重复key值元素

构造和赋值

构造:
map<t1,t2>mp; /map默认构造函数:
map(const map &mp); //拷贝构造函数
赋值:
map& operator=(const map &mp); //重载等号操作符

注意:⭐遍历的方法:

代码示例:

#include<iostream>
#include<map>
#include<algorithm>
using namespace std;
void printMap(map<int, int>& a)
{
	for (map<int, int>::iterator it = a.begin(); it!= a.end();it++)
	{
		cout << "key= " << it->first << " value=" << it->second << endl;
	}
}
void test1()
{
	//创建map容器
	map<int, int> a;
	a.insert(pair<int,int>(0,12));
	a.insert(pair<int, int>(2, 14));
	a.insert(pair<int, int>(3, 23));
	a.insert(pair<int, int>(1, 2));
	a.insert(pair<int, int>(4, 45));
	//printMap(a);

	map<int, int>b;
	b = a;
	printMap(b);
}

int main() {
	test1();
	return 0;
}

大小

size(); //返回容器中元素的数目
empty(); //判断容器是否为空
swap(st); //交换两个集合容器

插入和删除

insert(elem); //在容器中插入元素。这个里面要写pair数组来赋值插入
clear(); //清除所有元素
erase(pos); //删除pos迭代器所指的元素,返回下一个元素的迭代器。
erase(beg,end); //删除区间(beg,end)的所有元素,返回下一个元素的迭代器。
erase(key); //删除容器中值为key的元素。

插入数组代码示例:

#include<iostream>
#include<map>
#include<algorithm>
using namespace std;
//高效率,高性能,因为有个key起索引作用
//且会直接按照key值排序
//底层来用二叉树实现的
//map的key值不可重复,value可以重复
void printMap(map<int, int>& a)
{
	for (map<int, int>::iterator it = a.begin(); it!= a.end();it++)
	{
		cout << "key= " << it->first << " value=" << it->second << endl;
	}
}
void test1()
{
	map<int, int> a;
	a.insert(pair<int,int>(0,12));
	a.insert(pair<int, int>(2, 14));
	a.insert(pair<int, int>(3, 23));
	a.insert(pair<int, int>(1, 2));
	a.insert(pair<int, int>(4, 45));
	printMap(a);
}

int main() {
	test1();
	return 0;
}

查找

find(key); //查找key是否存在,返回该键的元素的元素的迭代器;若不存在,返回set.end();
count(key); //统计key的元素个数

count和set里的一样,由于不可以出现重复数据,则返回要么0或者1

变排序规则

利用仿函数来改变排序规则——

注意:如果把不改变数据成员的函数都加上const关键字进行标识,显然可提高程序的可读性。 其实,它还能提高程序的可靠性,已定义成const的成员函数,一旦企图修改数据成员的值,则编译器按错误处理。

代码示例:

#include<iostream>
#include<map>
#include<stdlib.h>
using namespace std;

class MyCompare
{
public:
	bool operator()(int m, int n)const//要加一个const,对于不同的编译器可能不一样,这个如果不加,就发生错误
	{
		return m > n;
	}
};



void test2()
{
	map<int,int,MyCompare> a;
	a.insert(make_pair(1, 10));
	a.insert(make_pair(2, 20));
	a.insert(make_pair(3, 30));
	a.insert(make_pair(4, 40));
	a.insert(make_pair(5, 50));
	for (map<int,int,MyCompare>::iterator it = a.begin(); it != a.end(); it++)
	{
		cout << "key= " << it->first << " value=" << it->second << endl;
	}
}
int main() {
	test2();
	system("pause");
	return 0;
}

🎄STL函数对象

函数对象

概念:

一个类重载了函数调用符号——(),然后其类对象可以进行类似于函数调用的操作,因此被称为函数对象

而函数对象进行调用操作由于比较像函数调用嘛又被称为仿函数

注意:这里所有的函数对象阿、仿函数等概念都是指一个

区别和共性:

由于它并不是真正的函数调用,因此会有几点区别但也有一样的地方——

1.函数对象可以有自己的属性,而普通函数没有

2.函数对象可以像普通函数调用一样有参数,有返回值

3.函数对象可以作为参数传递

谓词

谓词就是在函数对象的基础上加上一个条件——返回类型为bool类型

而且分为两类:

参数为1个的——一元谓词

参数为2个的——二元谓词

内置的函数对象

对于c++,编译器会有一些内置的函数对象,不过需要加头文件——#include<function>

分类:

算数仿函数

 实现四则运算的函数对象(仿函数)

仿函数原型:
template<class T>T pluS<T>//加法仿函数

template<class T>T minus<T>//减法仿函数

template<class T>T multiplies<T>//乘法仿函数

template<class T>T divides<T>//除法仿函数

template<class T>T modulus<T>//取模仿函数

template<class T>T negate<T>//取反仿函数

只有取反的是一元函数,其余皆为二元

代码示例:

#include<iostream>
#include<functional>
using namespace std;
//内建函数对象——算数仿函数
//1.取反仿函数
//2.加法仿函数

void test1()
{
	negate<int> a;//创建的函数对象
	cout << a(10) << endl;//-10
	plus<int>b;//只写一个数据类型
	cout << b(1, 2) << endl;//3
}

int main() {
	test1();
	return 0;
}

关系仿函数

 实现关系对比的仿函数

template<class T>bool equal to<T>//等于
template<class T> bool not equal to<T>//不等于template<class T> bool greater<T>//大于
template<class T> bool greater equal<T>//大于等于
template<class T> bool less<T>//小于
template<class T> bool less equal<T>//小于等于

代码示例:——通过大于的关系仿函数来实现降序排列

#include<iostream>
#include<functional>
#include<vector>
#include<algorithm>
using namespace std;
//内建函数对象——关系仿函数

class MYcompare
{
public:
	bool operator()(int a, int b)
	{
		return a > b;
	}
};

void test1()
{
	vector <int> v;
	v.push_back(1);
	v.push_back(5);
	v.push_back(2);
	v.push_back(4);
	v.push_back(3);

	for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << *it;
	}cout << endl;
	sort(v.begin(), v.end(), MYcompare());//自己创建的仿函数来实现降序
	sort(v.begin(), v.end(), greater<int>());//内建函数对象

	for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << *it;
	}cout << endl;
}

int main() {
	test1();
	return 0;
}

逻辑仿函数

 实现逻辑运算的仿函数

template<class T> bool logical and<T>//逻辑与

template<class T> bool logical or<T>//逻辑或

template<class T> bool logical not<T>//逻辑非
在实际开发中基本用不到

代码案例:

#include<iostream>
#include<functional>
#include<vector>
#include<algorithm>
using namespace std;
//内建函数对象——关系仿函数



void test1()
{
	vector <int> v;
	v.push_back(true);//1
	v.push_back(false);//0
	v.push_back(true);//1
	v.push_back(true);//1
	v.push_back(false);//0

	for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << *it;
	}cout << endl;
	
	vector <int>b;
	b.resize(v.size());//要提前开辟一块空间,再搬运

	transform(v.begin(), v.end(), b.begin(),logical_not<bool>());//这是个内置的函数

	for (vector<int>::iterator it = b.begin(); it != b.end(); it++)
	{
		cout << *it;
	}cout << endl;
}

int main() {
	test1();
	return 0;
}

🎄STL算法

这里介绍一些比较常用的算法——一般需要包含的头文件是——<algorithm>

常用算法:

1.遍历算法

for_each

for_each(iterator begin,iterator end,func)

三个参数分别是——开始的迭代器,终止迭代器,函数或者函数对象

transform

将一个容器里的内容搬运到另一个容器中

transform(iterator begin1,iterator end1,iterator begin2 ,func)

参数分别对应原容器起始迭代器,原终止迭代器,新容器起始迭代器,函数或是函数对象

2.查找算法 

find

查找目标元素,找到返回指定元素的迭代器,找不到返回终止迭代器end()

find(iterator begin.iterator end,val);
分别对应着起始迭代器、终止迭代器、目标元素

find_if

按条件查找元素,找到返回所在位置迭代器,否则返回终止迭代器end();

find_if(iterator begin,iterator  end,_Pred)
begin    起始迭代器
end      终止迭代器
_Pred    函数或谓词
adjacent_find

查找相邻重复元素,找到返回所在位置迭代器,否则返回终止选代器end();
adjacent find(iterator begin,iterator end);
起始迭代器,终止迭代器

查找指定元素是否存在,存在返回true,否则返回false
binary_search(iterator begin,iterator end,val);
分别代表:起始迭代器、终止迭代器、目标元素

count

统计元素个数
count(iterator begin,iterator end,val);

参数分别为:起始迭代器、终止迭代器、目标元素

count_if

按条件统计元素个数
count_if(iterator begin,iterator end,_Pred);

起始迭代器、终止迭代器、谓词(也就是条件)

3.排序算法

sort

对容器内元素进行排序
sort(iterator begin,iterator end, Pred);
起始迭代器、终止迭代器、谓词(条件,不填是升序)

random_shuffle

洗牌,指定范围内元素随机调整次序
random shuffle(iterator begin,iterator end);

起始迭代器、终止迭代器

merge

将两个容器元素合并,并存储到另一个容器中

 merge(iterator begin1,iterator end1,iterator begin2,iterator end2,iterator dest);
 参数分别为: 容器1起始迭代器、 容器1终止迭代器、容器2起始迭代器、容器2终止迭代器、目标存储迭代器

reverse

将范围内元素反转
reverse(iterator begin,iterator end);

起始迭代器、终止迭代器

4.拷贝和替换函数

copy

将容器指定范围内元素拷贝到另一容器中

 copy(iterator begin1,iterator end1,iterator dest);
 begin1    容器1起始迭代器
 end1      容器1终止迭代器
 dest      目标存储迭代器

replace

将容器中指定范围内的所有指定元素替换为新的元素

replace(iterator begin,iterator end,oldval,newval);
begin     起始迭代器
end       终止迭代器
oldval    旧元素
newval    新元素
replace_if

容器内指定范围内满足条件的元素替换为新的元素

replace_if(iterator begin,iterator end,_Pred,newval);
begin     起始迭代器
end       终止迭代器
_Pred     谓词
newval    新元素
swap

交换2个相同类型容器的元素

 swap(container c1,container c2);
 c1    容器1
 c2    容器2

5.算术生成算法

fill

向容器中添加指定元素

 fill(iterator begin,iterator end,val);
 begin     起始迭代器
 end       终止迭代器
 val       要填充的值

accumulate

将容器指定范围内元素拷贝到另一容器中

 accumulate(iterator begin,iterator end,val);
 begin     起始迭代器
 end       终止迭代器
 val       起始值

6.集合算法

set_intersection

求两个容器的交集

set_intersection(iterator begin1,iterator end1,iterator begin2,iterator end2,iterator dest);
 begin1    容器1起始迭代器
 end1      容器1终止迭代器
 begin2    容器2起始迭代器
 end2      容器2终止迭代器
 dest      目标存储迭代器

🎄总结

到这里已经基本总结完毕了有关c++的stl知识,由于文章篇幅比较长,有些细节没有很完善,本篇文章会继续更新,欢迎收藏,跟进后续内容。(●'◡'●)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1522163.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

c语言:操作符详解(上)

目录 一、操作符的分类二、二进制和进制转换1.2进制转10进制2.10进制转2进制3.2进制转8进制4.2进制转16进制 三、原码、反码、补码四、算术操作符、-、*、/、%1.**和-**2.*3./4.% 五、移位操作符1.左移操作符2.右移操作符 六、位操作符&#xff1a;&、|、^、~七、赋值操作符…

口腔管理平台 |基于springboot框架+ Mysql+Java+B/S结构的口腔管理平台 设计与实现(可运行源码+数据库+lw文档)

推荐阅读100套最新项目 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 目录 前台功能效果图 管理员功能登录前台功能效果图 会员功能 系统功能设计 数据库E-R图设计 lunwen参考…

操作系统知识-操作系统作用+进程管理-嵌入式系统设计师备考笔记

0、前言 本专栏为个人备考软考嵌入式系统设计师的复习笔记&#xff0c;未经本人许可&#xff0c;请勿转载&#xff0c;如发现本笔记内容的错误还望各位不吝赐教&#xff08;笔记内容可能有误怕产生错误引导&#xff09;。 本章的主要内容见下图&#xff1a; 1、操作系统的作用…

7. 字符串和集合(重点)

常见API API &#xff08;全称 Application Programming Interface&#xff1a;应用程序编程接口&#xff09;就是别人写好的一些程序&#xff0c;给咱们程序员直接拿去调用即可解决问题的。 1 包 1.1 什么是包&#xff1f; 包是用来分门别类的管理各种不同程序的&#xff…

电源适配器

电源适配器 1. 选购指南2. 接口测量方法3. 电源接口4. 抗干扰磁环&#xff0c;稳定输出References 1. 选购指南 插头尺度相同&#xff0c;供电电压 (V) 相同&#xff0c;电流 (A) > 原来的电流 (A) INPUT (输入)&#xff0c;OUTPUT (输出) 2. 接口测量方法 3. 电源接口 外…

sqllab第二十五A关通关笔记

知识点&#xff1a; 数值型注入双写绕过 oorranand这里不能用错误注入&#xff08;固定错误回显信息&#xff09;联合注入 测试发现跟25关好像一样&#xff0c;就是过滤了and or # 等东西 构造payload:id1/0 发现成功运算了&#xff0c;这是一个数值型的注入 构造payload:id…

Arthas使用案例(二)

说明&#xff1a;记录一次使用Arthas排查测试环境正在运行的项目BUG&#xff1b; 场景 有一个定时任务&#xff0c;该定时任务是定时去拉取某FTP服务器上的文件&#xff0c;进行备份、读取、解析等一系列操作。 而现在&#xff0c;因为开发环境是Windows&#xff0c; 线上项…

pta上的几个例题

c语言中的小小白-CSDN博客c语言中的小小白关注算法,c,c语言,贪心算法,链表,mysql,动态规划,后端,线性回归,数据结构,排序算法领域.https://blog.csdn.net/bhbcdxb123?spm1001.2014.3001.5343 给大家分享一句我很喜欢我话&#xff1a; 知不足而奋进&#xff0c;望远山而前行&am…

9.用FFmpeg测试H.264文件的解码时间

1. Essence of Method 要测试对H.264文件的解码时间&#xff0c;可以使用FFmpeg进行操作。FFmpeg是一个开源的多媒体处理工具&#xff0c;可以用来处理视频和音频文件&#xff0c;包括解码H.264文件。以下是使用FFmpeg的命令行来测试解码时间的方法&#xff1a; ffmpeg -i in…

四连杆机构运动学仿真 | 【Matlab源码+理论公式文本】

【程序简介】&#x1f4bb;&#x1f50d; 本程序通过matlab实现了四连杆机构的运动学仿真编程&#xff0c;动态展现了四连杆机构的运动动画&#xff0c;同时给出了角位移、角速度和角加速度的时程曲线&#xff0c;除了程序本身&#xff0c;还提供了机构运动学公式推导文档&…

更安全的C gets()和str* 以及fgets和strcspn的用法

#include <stdio.h>int main() {char *str;gets(str);puts(str);return(0); }可以说全是错误 首先char *str没有指向一个分配好的地址&#xff0c;就直接读入&#xff0c;危险 ps: 怎么理解char *str "Hello World" 是将一个存储在一个只读的数据段中字符串常…

字符函数以及字符串函数

1.strlen的使用和模拟实现 • 字符串以 \0 作为结束标志&#xff0c;strlen函数返回的是在字符串中 \0 前⾯出现的字符个数&#xff08;不包 含 \0 )。 • 参数指向的字符串必须要以 \0 结束。 • 注意函数的返回值为size_t&#xff0c;是⽆符号的&#xff08; 易错 &#xff…

【C++】了解一下编码

个人主页 &#xff1a; zxctscl 如有转载请先通知 文章目录 1. 前言2. ASCII编码3. unicode4. GBK5. 类型转换 1. 前言 看到string里面还有Template instantiations&#xff1a; string其实是basic_string<char>&#xff0c;它还是一个模板。 再看看wstring&#xff1…

音频的录制及播放

在终端安装好pip install pyaudio&#xff0c;在pycharm中敲入录音的代码&#xff0c;然后点击运行可以在10s内进行录音&#xff0c;录音后的音频会保存在与录音代码同一路径项目中&#xff0c;然后再新建项目敲入播放的代码&#xff0c;点击运行&#xff0c;会把录入的录音进行…

更改el-tabs默认样式,实现tab标签居中显示,标签对应内容使用另一个div显示

首先看效果图 如图所示&#xff0c;标签在浏览器窗口居中&#xff0c;但是下面的内容依然是默认从左到右&#xff0c;不会受到tab样式的影响 <template><div><div style"display: flex; justify-content: center; align-items: center;"><el-…

文献阅读及笔记

每个阶段&#xff0c;该看什么文献 当我们刚开始接触课题时&#xff0c;对这个研究方向一无所知&#xff0c;可以选择硕博学位论文、领域大牛的文献综述当我们已经对课题有了解&#xff0c;处于深化认识的阶段&#xff0c;可以选择行业最新的论文&#xff0c;领域大牛的文献综…

探讨大世界游戏的制作流程及技术——大场景制作技术概况篇

接上文&#xff0c;我们接下来了解一下大世界场景制作技术有哪些&#xff0c;本篇旨在给大家过一遍目前业界的做法&#xff0c;能让大家有一个宏观的知识蓝图。实际上&#xff0c;针对不同的游戏类型和美术风格&#xff0c;制作技术在细节上有着非常大的不同&#xff0c;业界目…

开环端到端自动驾驶: 到底行不行

开环端到端自动驾驶&#xff1a; 到底行不行 附赠全面专业的自动驾驶学习资料&#xff1a;直达链接 TLDR: 别在nuScenes上做开环端到端自动驾驶刷点了。 论文&#xff1a; https://arxiv.org/pdf/2312.03031.pdf github: https://github.com/NVlabs/BEV-Planner 前言 Uni…

set与zset数据类型

set类型基础 redis集合(set)类型和list列表类型类似&#xff0c;都可以用来存储多个字符串元素的 集合。但是和list不同的是set集合当中不允许重复的元素。而且set集合当中元素是没有顺序的&#xff0c;不存在元素下标。 redis的set类型是使用哈希表构造的&#xff0c;因此复…

宠物疾病 与 光线疗法

人类与动物以及大自然是相辅相成的。人离开动物将无法生存&#xff0c;对于动物我们尽力去保护&#xff0c;与大自然和谐稳定生存发展。 生息在地球上的所有动物、在自然太阳光奇妙的作用下、生长发育。太阳光的能量使它们不断进化、繁衍种族。现在、生物能够生存、全仰仗于太…