Aprendizaje C ++ STL (1) -contenedor

Notas de estudio de C ++ STL (1) -contenedor

trivialidades

 Para prepararme para la Copa Blue Bridge, tengo que aprender la parte C ++ STL, lo que puede ahorrar mucho tiempo; esta nota es para recordar cuando mire el curso del programador Dark Horse en la estación B:

El ingenio de los programadores de Dark Horse | Tutorial de C ++ de programación de entrada 0 a 1, aprender a programar ya no es difícil

1. Introducción a STL

1.1 Conceptos básicos de STL

  • STL (Biblioteca de plantillas estándar, biblioteca de plantillas estándar)
  • STL se divide ampliamente en: ① contenedor (contenedor) ② algoritmo (algoritmo) ③ iterador (iterador)
  • Los contenedores y algoritmos están conectados a través de iteradores.
  • Casi todo el código en STL utiliza clases de plantilla o funciones de plantilla.

1.2 Seis componentes de STL

STL se divide aproximadamente en seis tipos: contenedores, algoritmos, iteradores , functores, adaptadores (adaptadores) y configuradores de espacio.

  1. Contenedores: varias estructuras de datos, como vector, lista, deque, conjunto, mapa, etc., utilizadas para almacenar datos. 2.
  Algoritmos: varios algoritmos de uso común, como ordenar, buscar, copiar, etc.
  3. Iteradores: contenedores y algoritmos Entre el conector
  4. Functor: El comportamiento es similar a una función, como una determinada estrategia del algoritmo
  5. Adaptador: se utiliza para modificar la interfaz contenedor o funtor o iterador
  6. Configurador de espacio: responsable de la configuración y gestión del espacio

1.3 Contenedores, Algoritmos, Iteradores en STL

1.3.1 Contenedores

Contenedores :
 Los contenedores STL de datos de lugar son algunas de las estructuras de datos más utilizadas. Estructuras de datos de uso común
 : matrices, listas vinculadas, árboles, colas, colecciones y tablas de mapeo.
 Estos contenedores se dividen en dos tipos : contenedores secuenciales y contenedores asociativos :
  contenedores secuenciales : énfasis en el orden de los valores, cada elemento tiene una posición fija
  contenedor asociativo : estructura de árbol binario, no existe una relación de orden físico estricta

1.3.2 Algoritmos

Algoritmo : pasos limitados para resolver problemas lógicos/matemáticos
 Los algoritmos se dividen en: algoritmo de cambio cualitativo, algoritmo de cambio no cualitativo
 Cambio cualitativo: algoritmo que cambia el contenido del elemento, elimina copia
 cambio no cualitativo: la operación no cambia el contenido del elemento, búsqueda de conteo

1.3.3 Iteradores

Iteradores: los algoritmos necesitan usar iteradores para acceder a los datos en el contenedor.
 Cada contenedor tiene su propio iterador.
用法类似于指针

Los tipos de iteradores comunes son: iterador bidireccional, iterador de acceso aleatorio

1.4 Introducción al iterador del algoritmo de contenedor

 Después de comprender el concepto del iterador del algoritmo de contenedor STL, use el código para profundizar la comprensión
 del contenedor más utilizado: Vector , que puede entenderse como una matriz para demostrar.

1.4.1 tipos de datos integrados para almacenes vectoriales

 contenedor: vector
 algoritmo: for_each
 iterador:vector< int>::iterator

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

void myPrint(int val){
    
    
	printf("%d\n",val);
}
void test01(){
    
    
	vector<int> v;//创建vector容器对象,通过模板参数指定容器中存放的数据类型 
	
	v.push_back(10); //放入数据 
	v.push_back(20);
	v.push_back(30);
	
	/* 第一种遍历
	 * v.begin()返回指向容器中第一个数据的迭代器
	 * v.end()返回指向容器中最后一个数据下一位的迭代器
	 * vector<int>::iterator 是vector<int>类型的迭代器
	 */
	vector<int>::iterator itBegin = v.begin();	//itBegin指向第一个元素 
	vector<int>::iterator itEnd = v.end();		//itEnd指向最后一个元素的下一位 
	while(itBegin != itEnd){
    
    
		cout<<*itBegin<<endl;
		itBegin++;
	}
	
	/*第二种遍历*/ 
	for(vector<int>::iterator it = v.begin();it!=v.end();it++){
    
    
		cout<<*it<<endl;
	}
	
	/*第三种遍历:利用STL提供的遍历算法*/
	for_each(v.begin(),v.end(),myPrint); 
	
}
int main(){
    
    
	test01();
	return 0;
} 

1.4.2 tipos de datos personalizados para tiendas vectoriales

(*it)到最后是什么类型,可以直接看迭代器尖括号里面的东西即可
就像下面的
函数1,(*it)是Person类型
函数2,(*it)是Person * 类型
#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
using namespace std;

class Person{
    
    
	public: 
		Person(string name, int age){
    
    
			this->name = name;
			this->age = age;
		}
		string name;
		int age;
}; 

void test01(){
    
    
	vector<Person> v;
	
	Person p1("zhao",1);
	Person p2("qina",2);
	Person p3("swun",3);
	
	//存放数据 
	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	
	//遍历数据 
	for(vector<Person>::iterator it=v.begin();it!=v.end();it++){
    
    
		cout<<(*it).name<<" "<<(*it).age<<endl;
	}
}

void test02(){
    
    
	vector<Person*> v;
	
	Person p1("zhao",1);
	Person p2("qina",2);
	Person p3("swun",3);
	
	//存放数据 
	v.push_back(&p1);
	v.push_back(&p2);
	v.push_back(&p3);
	
	//遍历数据 
	//*在这里*it是Person类型的指针*/ 
	for(vector<Person*>::iterator it=v.begin();it!=v.end();it++){
    
    
		cout<<(*it)->name<<" "<<(*it)->age<<endl;
	}
}

int main(){
    
    
	test01();
	test02();
	return 0;
} 

1.4.3 contenedor anidado de contenedor vectorial

Objetivo de aprendizaje: anidar contenedores dentro de contenedores, recorrer todos los datos de salida.
Ejemplo:

#include<iostream>
#include<vector>
using namespace std;

//容器嵌套容器 
void test01(){
    
    
	vector< vector<int> >v;	

	vector<int> v1;
	vector<int> v2;
	vector<int> v3;

	for(int i = 0;i<3;i++){
    
    
		v1.push_back(i);
		v2.push_back(i+1);
		v3.push_back(i+2);		
	}
	
	//将小容器插入到大容器中 
	v.push_back(v1); 
	v.push_back(v2); 
	v.push_back(v3); 
	
	//通过大容器,将数据遍历
	for(vector<vector<int> >::iterator it=v.begin();it!=v.end();it++){
    
    
		//(*it) ----------容器 vector<int> 
		for(vector<int>::iterator vit=(*it).begin();vit != (*it).end();vit++){
    
    
			cout<< *vit <<" "; 
		}
		cout<<endl;
	} 
}
int main(){
    
    
	test01();
	return 0;
}


2. Contenedores STL de uso común

2.1 contenedor de cuerdas

2.1.1 Concepto básico de cadena

Naturaleza:

 - string是C++风格的字符串,而string本质上是一个类
La diferencia entre cadena y carácter *:
 - char *是一个指针
 - string是一个类,类内部封装了char*,是char*型的容器

Características:

 - string类内部封装了许多成员方法(例如:find,copy,delete)
 - string管理char*所分配的空间,不用担心下标越界

2.1.2 Constructor de cadenas

Prototipo constructor:

 - string();				//创建空的字符串
 - string(const char* s);	//使用字符串s初始化
 - string(const string& str);//使用字符串对象来初始化另一个string对象
 - string(int n,char c);	//使用n个字符c初始化
/*example*/
#include<iostream>
#include<vector>
using namespace std;

//string初始化 
void test01(){
    
    
	string str1;
	string str2("字符串2");
	string str3(str2);
	string str4(6,'a');

	cout << str1 << endl; 
	cout << str2 << endl;
	cout << str3 << endl;
	cout << str4 << endl;
}
int main(){
    
    
	test01();
	return 0;
}

2.1.3 Operación de asignación de cadenas

Función descriptiva:

 - 给string字符串赋值(= 或者assign)

función de prototipo de operación de asignación

赋值操作一共有两种:一种是直接用等号=,原型如下
 - string& operator=(const char* s);//char* 类型字符串,赋值给当前字符串
 - string& operator=(const string &s);//把字符串赋值给当前的字符串
 - string& operator=(char c);//字符赋值给当前的字符串

另一种是assign()
 - 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赋给当前字符
/*example*/
#include<iostream>
using namespace std;

//string初始化 
void test01(){
    
    
	string str1;
	string str2;
	string str3;
	string str4;
	string str5;
	string str6;
	string str7;
	
	/*用等号来赋值*/
	str1 = "hello world"; 
	str2 = str1;
	str3 = "a";
	
	str4.assign("helloworld");
	str5.assign("string5",3);
	str6.assign(str1);
	str7.assign(5,'a');
	
	cout<<str1<<endl;
	cout<<str2<<endl;
	cout<<str3<<endl;
	cout<<str4<<endl;
	cout<<str5<<endl;
	cout<<str6<<endl;
	cout<<str7<<endl;
}
int main(){
    
    
	test01();
	return 0;
}

Resumen:
 hay muchas formas de asignar valores a cadenas, pero usar operator= es un método más práctico

2.1.4 Concatenación de cadenas

Función descriptiva:

 - 实现在字符串的末尾拼接字符串

Prototipo de función:

 - 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个字符连接到字符串结尾
/*exanmple*/
	string str1 = "I";
	string str2 = "you,li ming";
	string str3 = "Life";
	
	str1 += "love";	//追加字符串
	str1 += " ";	//追加单个字符
	str1 += str2;	//拼接字符串对象
	cout<<str1<<endl;//Ilove you
	
	str3.append(" is ");
	str3.append("movieasdfasdf",5);
	str3.append(str2,0,3);
	cout<<str3<<endl;//Life is movieyou

Resumir:

如果使用append(const string &s, int pos, int n)函数,
应当弄明白字符的位置是从0开始的

2.1.5 búsqueda y reemplazo de cadenas

Función descriptiva:

查找:查找指定字符串是否存在
替换:在指定的位置替换字符串

Prototipo de función:

 - int find(const string &str,int pos=0) const; 	从pos位置开始查找str第一次出现的位置
 - int find(const char *s,int pos=0) const;			从pos位置开始查找s第一次出现位置
 - int find(const char *s,int pos=0,int n) const; 	从pos位置查找s的前n个字符第一次位置
 - int find(const char c,int pos=0)  const; 		从pos位置查找字符c的第一次出现位置
 - int rfind(const string &str,int pos=npos) const; 从pos开始查找str最后一次位置,
 - int rfind(const char *s,int pos=npos) const; 	从pos开始查找s最后一次出现位置,
 - int rfind(const char *s,int pos,int n) const; 	从pos查找s的前n个字符最后一次位置
 - int rfind(const char c,int pos=0) 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的区别:find默认从左往右查找,而rfind则代表从右往左查;
find找到字符串后返回查找到的字符串的第一个字符的下标,找不到则返回-1;
replace替换时要指定从哪儿个位置开始起,其后有多少个字符,替换成什么样的字符串。

  Consejos: cuando C ++ declara una función, seguida de una constante es para limitar el tipo de función a una función miembro constante, y una función miembro constante se refiere a una función que no puede cambiar el valor de una variable miembro. Por ejemplo, "double d() const;", el "const" en él limita que la función d() no puede tener ninguna función para cambiar el valor de la variable miembro del objeto al que pertenece, y si la hay, Se informará un error en la etapa de compilación. Su función principal es aclarar el significado de las funciones miembro. Podemos agregar descripciones constantes a los prototipos de funciones de funciones miembro que no cambian el objeto. Este formulario se puede utilizar cuando sea necesario aumentar la legibilidad y reducir los errores lógicos.

/*查找举例*/
void test01(){
    
    
	string str1 = "zainashandenaoyouyiqunljl";
	int pos = str1.find("i");
	if (pos == -1)
		cout << "未找到" << endl;
	else
		cout << pos << endl;
	pos = str1.rfind("i");
	cout<<pos<<endl;
}
void test02(){
    
    
	string str1 = "zainashandenaoyouyiqunljl";
	/*从一号字符起3个字符用1111替换 */
	str1.replace(1,3,"1111") ;
	cout<<str1<<endl;
}

2.1.6 Comparación de cadenas de cadenas

Comparar por:

比较字符的ASCII码值
	= return 0
	> return 1
	< return -1

Prototipo de función:

在string类内部有这两个操作:
int compare(const string &s) const; //与string对象字符串s比较
int compare(const char *s) const; //与字符串s比较
/*example*/
string str1 = "hello!";
string str2 = "hillo!";
if (str1.compare(str2) == 0){
    
    
	cout << "str1和str2相同!" << endl;
}else if(str1.compare(str2) ==-1){
    
    
	cout << "str1小于str2!" << endl;
}else
	cout<<"str1大于str2"<<endl;

Resumir:

一般用来比较字符串是否相等

2.1.7 acceso a caracteres de cadena

Hay dos formas de acceder a un solo carácter en una cadena.

在string类内部有这两个操作:
    char& operator[](int n); //通过[]方式取字符
    char& at(int n); //通过string类内部at方法获取字符
/*example*/
string str = "hello world";
cout<<str[1]<<endl;
for(int i=0;i<str.size();i++)
	cout<<str.at(i)<<endl;
/*修改*/
str[0] = 'x';
str.at(1) = 'x';
cout<<str<<endl;

2.1.8 inserción y eliminación de cadenas

Prototipo de función:

在string类内部有这两个操作:
	string& insert(int pos, const char* s);//通过指向字符常量区域的指针对调用该成员函数的对象来插入字符
	string &insert(int pos,const string &str); //通过string类型的对象插入字符
	string &insert(int pos,int n,char c); //在指定位置插入n个字符c
	string &erase(int pos,int n=npos); //删除从pos开始的n个字符 
str.insert(1,"ag")

Resumir

	通常情况下直接str.insert(1,"ag")就行;

2.1.8 Adquisición de subcadenas de cadenas

Prototipo de función:

string substr(int pos = 0;int n=npos) const;
/*useful exanmple:输入邮箱,自动获取邮箱账号*/
void test02(){
    
    
	string str;
	cin >> str;
	string userName = str.substr(0,str.find("@"));
	cout<<userName<<endl;
}

El siguiente es el segundo tipo de contenedor: vector

2.2 contenedores vectoriales

2.2.1 Concepto básico de vector

Función:
  la estructura de datos vectoriales es muy similar a una matriz, también conocida como matriz de un solo extremo .
La diferencia entre un vector y una matriz ordinaria :
  la diferencia es que una matriz es un espacio estático, mientras que un vector se puede expandir dinámicamente .
.Expansión dinámica:
  ① En lugar de agregar un nuevo espacio después del espacio original, busque un espacio de memoria más grande y luego copie los datos originales al nuevo espacio para liberar el espacio original.
  ②El iterador del contenedor de vectores es un iterador que admite acceso aleatorio.

2.2.2 constructor de vectores

Prototipo de función:

vector<T> v; //采用模板实现类实现,默认构造函数
vector(v.begin(), v.end()); //将v[begin(), end()]区间中的元素拷贝给本身
vector(n, elem); //构造函数将n个elem拷贝给本身
vector(const vector &vec); //拷贝构造函数
vector<int>v1;  					 // 1.默认构造
vector<int> v2(v1.begin(), v1.end());//2.区间方式进行构造
vector<int> v3(10, 100);			 //3.n个elem方式构造
vector<int> v4(v3);					 //拷贝构造

2.2.3 Operación de asignación de vectores

Prototipo de función:

vector &operator = (const vector &vec); //重载等号操作符
assign(begin,end);//将[ begin, end ]区间的数据拷贝赋值给本身
assign(n,elem); //将n个elem拷贝赋值给本身 

Ejemplo:

vector<int>v1 = v;
vector<int>v2;
v2.assign(v.begin(),v.end());
vector v3;
v3.assgin(12,1001);

2.2.4 Capacidad y tamaño del vector

Prototipo de función:

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

总结:
 - 判断是否为空--- empty()
 - 返回元素个数--- size()
 - 返回容量个数--- capacity()
 - 重新指定大小--- resize()

Ejemplo:

#include<iostream>
#include<vector>
using namespace std;

void printVector(vector<int>& v)
{
    
    
	for (vector<int>::iterator it = v.begin(); it != v.end(); ++it)
	{
    
    
		cout << *it << " ";
	}
	cout << endl;
}
/*exanmple*/
void test02(){
    
    
	vector<int>v;
	for(int i=0;i<10;i++){
    
    
		v.push_back(i);
	}
	cout<<v.empty()<<endl;
	cout<<v.capacity()<<endl;
	cout<<v.size()<<endl;
	v.resize(6);
	printVector(v);
	v.resize(126,9);
	printVector(v);
}
int main(){
    
    
	test02();
	return 0;
}

2.2.5 inserción y eliminación de vectores

Prototipo de función:

push_back(ele) //尾部插入元素
pop_back() 	   //删除尾部元素
insert(const_iterator pos,ele) //迭代器指向位置pos插入ele
insert(const_iterator pos,int count,ele) //迭代器指向pos插入count个元素ele
erase(const_iterator start,const_iterator end) //删除迭代器从start到end之间的元素
clear() //删除容器中所有元素
Resumen: insertar inserción de cola, insertar un elemento a través de un iterador e insertar un elemento en un rango a través de un iterador; eliminar una eliminación de cola, eliminar un elemento a través de un iterador y eliminar un elemento en un rango a través de un iterador; vaciar el elemento .

Ejemplo:

v.push_back(12);
v.pop_back();
v.insert(v.begin(),100);
v.insert(v.begin(),2,1000);
v.erase(v.begin());
v.erase(v.begin(),v.begin()++);
v.clear();

2.2.6 Acceso a datos del contenedor vectorial

Prototipo de función:

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

Ejemplo:

for(int i = 0;i < v.size();i++){
	cout << v[i] << endl;
	cout << v.at(i) <<endl;
}
v.front();
v.back();

2.2.6 contenedor de intercambio de vectores

Prototipo de función:

swap(vec): //将vec与本身的元素互换

Ejemplo:

v1.swap(v2);

efecto mágico:

有一说一,这个里面的那个利用匿名对象来收缩空间的方法胎牛皮了!!!!!!
#include<iostream>
#include<vector>
using namespace std;
 
void printvector(vector<int> &v)
{
    
    
	for(vector<int>::iterator it=v.begin();it!=v.end();it++)
		cout<<*it<<" ";
	cout<<endl;
}
 
 
void test1()
{
    
    
	cout<<"交换之前的两个容器:"<<endl;
	vector<int> v1;
	for(int i=0;i<10;i++)
		v1.push_back(i);
	printvector(v1);
 
	vector<int> v2;
	for(int i=9;i>=0;i--)
		v2.push_back(i);
	printvector(v2);
	
	cout<<"交换之后的两个容器:"<<endl;
	v1.swap(v2);
	printvector(v1);
	printvector(v2);
 } 
 
 
 void test2() //容器互换应用实例
 {
    
    
 	vector<int> v;
	for(int i=0;i<10000;i++)
		v.push_back(i); 
	cout<<"v的容量为:"<<v.capacity()<<" v的大小为: "<<v.size()<<endl;
	
	v.resize(5); //重新指定大小之后,容量不变,大小改变 
	cout<<"v的容量为:"<<v.capacity()<<" v的大小为: "<<v.size()<<endl;
	
	//利用swap收缩内存
	vector<int>(v).swap(v); //vector<int>(v): 匿名对象 
	cout<<"v的容量为:"<<v.capacity()<<" v的大小为: "<<v.size()<<endl;
 } 
 
int main()
{
    
    
	test1();
	test2();
	return 0;
}
 
/*
打印结果:
交换之前的两个容器:
0 1 2 3 4 5 6 7 8 9
9 8 7 6 5 4 3 2 1 0
交换之后的两个容器:
9 8 7 6 5 4 3 2 1 0
0 1 2 3 4 5 6 7 8 9
v的容量为:16384 v的大小为: 10000
v的容量为:16384 v的大小为: 5
v的容量为:5 v的大小为: 5
*/

2.2.6 espacio reservado vectorial

Función descriptiva:

减少vector在动态扩展容量时的扩展次数

Prototipo de función:

reserve(int len);  
容器预留len个元素长度,预留位置不初始化,元素不可访问

Ejemplo:

v.reserve(100000);


A continuación se muestra el deque.

2.3 contenedor deque

2.3.1 Concepto básico de contenedor deque

característica:

Matriz de doble extremo, que puede insertar y eliminar operaciones en la cabecera.
El iterador del contenedor deque también admite acceso aleatorio.
Al usarlo, debe incluir el archivo de encabezado:#include<deque>

Diferencia del vector:

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

internoEl principio de funcionamiento interno de deque:

deque内部有个中控器,维护每段缓冲区中的内容,缓冲区中存放真实数据
中控器维护的是每个缓冲区的地址,使得使用deque时像一片连续的内存空间

controlador central



2.3.2 constructor e iterador deque

Prototipo de función:

deque<T> deqT;            默认构造形式
deque(beg,end);           构造函数将[beg,end)区间中元素拷贝给本身
deque(n,elem);            构造函数将n个elem拷贝给本身
deque(const deque &deq);  拷贝构造函数

Ejemplo 1:

deque<int>dl;
for(int i=0;i<10;i++)
	dl.push_back(i);
deque<int>d2(dl.begin(),dl.end());
deque<int>d3(10,100);
deque<int>d4=d3;

iteradores:

Cuando es solo para recorrido sin modificación, se debe agregar que el contenedor del tipo constde palabra clave necesita un iterador para que no se informe ningún error.
constconst_iterator

Ejemplo 2:

void printDeque(const deque<int>&d){
    
    
	for(deque<int>::const_iterator it = d.begin();it!=d.end();it++){
    
    
		cout<<*it<<endl;
	}
}

2.3.3 operación de asignación deque

Prototipo de función:

deque& operator=(const deque &deq);      重载等号操作符
assign(beg,end);                         将[beg,end)区间中的数据拷贝赋值给本身
assign(n,elem);                          将n个elem拷贝赋值给本身

Ejemplo:

deque<int>d2;
d2=dl;

//assign赋值
deque<int>d3;
d3.assign(dl.begin(),dl.end());

deque<int>d4;
d4.assign(10,100);

2.3.4 operación de tamaño deque

Puntos a tener en cuenta:

deque容器是没有容量这个概念的,
所以不像vector中有capacity函数

Prototipo de función:

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

Resumir:

判断是否为空 --- empty
返回元素个数 --- size
重新指定个数 --- resize

2.3.5 inserción y eliminación deque

Prototipo de función:

 两端插入操作: 
 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)区间的数据,无返回值
clear();                      清空容器的所有数据
erase(beg,end);               删除[beg,end)区间的数据,返回下一个数据的位置
erase(pos);                   删除pos位置的数据,返回下一个数据的位置

Ejemplo:

d.push_back(10);
d.pop_front();

2.3.6 acceso a datos deque

Prototipo de función:

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

Ejemplo:

for(i=0; i<d.size() ;i++);{
    
    
	cout<<d[i]<<" ";
	cout<<d.at(i)<<" ";
}

2.3.7 clasificación por deque

Aviso:

注意包含头文件<algorithm>;
sort算法默认升序;
对于支持随机访问的迭代器的容器,都可以利用sort算法直接对其进行排序;

algoritmo:

sort(iterator beg, iterator end);

Ejemplo:

sort(d1.begin(), d1.end());


A continuación se muestra la pila.

2.4 contenedor de pila

2.4.1 Concepto básico de pila

Concepto: la pila es una estructura de datos de primero en entrar
, primero en salir (primero en entrar, primero en salir),   tiene solo una salida;
 solo se puede acceder al elemento superior de la pila.
 stack no proporciona funciones transversales ni iteradores.
 Empujar push
 -Pop-pop
Alt.

2.4.2 Interfaz común de pila

Prototipo de función:

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

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

stack数据存取操作
	push(elem);//向栈顶添加元素
	pop();//从栈顶移除第一个元素
	top();//返回栈顶元素

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

Ejemplo:

s.top();//查看栈顶元素
s.pop();//出栈


El siguiente es queque.

Contenedor de cola 2.5

2.5.1 El concepto básico de queque

concepto:

La cola es una 先进先出estructura de datos (primero en entrar, primero en salir, FIFO) que tiene dos salidas. El
contenedor de la cola permite agregar elementos de un extremo y eliminar elementos del otro extremo.
Solo la suma en la 队头 front()cola 队尾 back()puede ser utilizada por el mundo exterior, por lo que la cola no permite Con el comportamiento transversal,
se llama a los datos en la cola, se 入队 push
llama a los datos fuera de la cola,出队 pop
Alt.

2.5.2 interfaz común queque

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

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

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

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

Resumir:

Entrar en la cola: push
Salir de la cola: pop
Devolver el elemento al principio de la cola
Devolver el elemento al final de la cola: back
Juzgar si el equipo está vacío: vacío
Devolver el tamaño de la cola: size

2.5.3 ejemplo de cola

#include <queue>
#include <string>
class Person
{
    
    
public:
	Person(string name, int age)
	{
    
    
		this->m_Name = name;
		this->m_Age = age;
	}

	string m_Name;
	int m_Age;
};

void test01() {
    
    

	//创建队列
	queue<Person> q;

	//准备数据
	Person p1("唐僧", 30);
	Person p2("孙悟空", 1000);
	Person p3("猪八戒", 900);
	Person p4("沙僧", 800);

	//向队列中添加元素  入队操作
	q.push(p1);
	q.push(p2);
	q.push(p3);
	q.push(p4);

	//队列不提供迭代器,更不支持随机访问	
	while (!q.empty()) {
    
    
		//输出队头元素
		cout << "队头元素-- 姓名: " << q.front().m_Name 
              << " 年龄: "<< q.front().m_Age << endl;
        
		cout << "队尾元素-- 姓名: " << q.back().m_Name  
              << " 年龄: " << q.back().m_Age << endl;
        
		cout << endl;
		//弹出队头元素
		q.pop();
	}
	cout << "队列大小为:" << q.size() << endl;
}

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


A continuación se muestra la lista

2.6 lista

2.6.1 Concepto básico de lista

优缺点:

Ventajas:
 los elementos se pueden insertar o eliminar rápidamente en cualquier posición;
Desventajas:
 la velocidad de recorrido del contenedor no es tan rápida como la de la matriz;
 ocupa más espacio que la matriz;

STL中的链表

La lista vinculada en STL es una lista vinculada circular bidireccional, y el iterador solo admite el movimiento hacia adelante y hacia atrás, que pertenece a双向迭代器
Alt.

Resumen: Lista y vector son los dos contenedores más utilizados en STL , cada uno con sus propias ventajas y desventajas.

2.6.2 constructor de listas

prototipo de función

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

Ejemplo:

list<int> l1; //默认构造
list<int> l2(l1.begin(), l1.end()); //区间方式构造(也属于拷贝)
list<int> l3(l2); //拷贝构造
list<int> l4(10, 999); //10个999(也属于拷贝)

3.7.3 asignación e intercambio de listas

Prototipo de función :

  • assign(begin, end);//Asigna la copia de los datos en el rango [inicio, fin) a sí mismo.
  • assign(n, elem);// Se asigna n copias de elementos a sí mismo
  • list& operator=(const list &lst);// Sobrecarga el operador igual
  • swap(lst);//Intercambia lst con sus propios elementos.

ejemplo

list<int>l1;
l2 = l1;
l3.assign(l2.begin(),l2.end());
l4.assign(10,100);
l4.swap(l3);

3.7.4 operación de tamaño de lista

prototipo de función

size();// Devuelve el número de elementos en el contenedor
empty();// Juzga si el contenedor está vacío
resize(num);// Vuelve a especificar la longitud del contenedor como num, si el contenedor se alarga, llena la nueva posición con el valor predeterminado. Si el contenedor se acorta, se eliminan los elementos al final que exceden la longitud del contenedor.
resize(num, elem);// Vuelva a especificar la longitud del contenedor como num. Si el contenedor se hace más largo, complete la nueva posición con el valor de elem. Si el contenedor se acorta, se eliminan los elementos al final que exceden la longitud del contenedor.

#include<iostream>
#include<string>
#include<list>
#include<algorithm>
using namespace std;

class Person//容器中要存放的数据类型
{
    
    
public:
	Person() {
    
    }
	Person(string name, int age)
	{
    
    
		m_name = name;
		m_age = age;
	}

	string m_name;
	int m_age;
};


void PrintList(const list<Person> &l)//打印容器中的数据
{
    
    
	for (list<Person>::const_iterator it = l.begin(); it != l.end(); it++)
	{
    
    
		cout << it->m_name << " " << it->m_age << endl;//用*it访问也可以,用指针也可以
	}
	cout << endl;
}

/*
size();                     //返回容器中元素的个数

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

resize(num);                //重新指定容器的长度为num,若容器变长,则以默认值填充新位置。

​							//如果容器变短,则末尾超出容器长度的元素被删除。

resize(num, elem);			//重新指定容器的长度为num,若容器变长,则以elem值填充新位置。

							//如果容器变短,则末尾超出容器长度的元素被删除。

*/

void test01(){
    
    //list大小操作
	list<Person> l;

	string Name = "ABC";
	for (int i = 0; i < 3; i++){
    
    //往容器里边插入三个数据
		string name = "李";
		name += Name[i];
		Person p(name, i + 20);
		l.push_back(p);
	}

	if (!l.empty()){
    
    
		cout << "容器不为空,大小为:"<<l.size() << endl;
	}
	else
		cout << "容器为空" << endl;	

	Person p("默认", 100);
	l.resize(10,p);
	l.resize(1);
	PrintList(l);

}

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

2.7.5 inserción y eliminación de listas

Prototipo de función:

* 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值匹配的元素。

2.7.6 acceso a datos de lista

Prototipo de función:

l.front();Devuelve el primer elemento del contenedor
l.back();Devuelve el último elemento del contenedor
Nota:

No se puede usar [] para acceder a los elementos en el contenedor de lista
No se puede usar at() para acceder a los elementos del contenedor de lista
La razón es: la lista es esencialmente una lista vinculada, que no es adecuada para almacenar datos en un espacio lineal continuo. y el iterador no admite acceso aleatorio (it = it+1 error), admite acceso bidireccional (it–)

l1.front();
l2.back();

2.7.7 Inversión y clasificación de listas

Prototipo de función:

reverse();Invertir
sort()clasificación de lista vinculada (función miembro, orden ascendente predeterminado, functor se puede usar para implementar orden descendente)

pista importante:

Todos los contenedores que no admiten iteradores de acceso aleatorio no pueden utilizar algoritmos estándar.
Los contenedores que no admiten iteradores de acceso aleatorio proporcionarán algunos algoritmos internamente. El
algoritmo de clasificación que viene con la lista por defecto es en orden ascendente de pequeño a grande. Función de devolución de llamada o funtor para implementar orden descendente (función de devolución de llamada aquí)

/*example*/
#include <iostream>
#include <list>
using namespace std;

template<class T>
void printList(const list<T>& L)
{
    
    
	for (list<T>::const_iterator it = L.begin(); it != L.end(); it++)
	{
    
    
		cout << *it << '\t';
	}
	cout << endl;
}

bool myCompare(int v1, int v2)
{
    
    
	//降序 让 第一个数 > 第二个数
	return v1 > v2;
}

//排序
void test2()
{
    
    
	list<int>L1;
	L1.push_back(20);
	L1.push_back(10);
	L1.push_back(50);
	L1.push_back(40);
	L1.push_back(30);

	cout << "排序前:" << endl;
	printList(L1);

	L1.sort();  //默认升序
	cout << "排序后:" << endl;
	printList(L1);

	L1.sort(myCompare);
	printList(L1);
}

int main()
{
    
    
	test2();
}

2.7.8 Caso de clasificación de listas

#include<iostream>
#include<string>
#include<sstream>
#include<list>
using namespace std;

/***/
class Person{
    
    
public:
	Person(string name,int age,int height){
    
    
		this->m_Name = name; 
		this->m_Age = age;
		this->m_Hight = height;
	}
	
	string printInfo()
    {
    
    
        stringstream temp;
        temp << "姓名:" << this->m_Name << "\t年龄:" << this->m_Age << "\t身高:" << this->m_Hight;
        return temp.str();
    }
	
	string m_Name;
	int m_Age;
	int m_Hight;
	
}; 
//指定排序规则
bool comparePerson(Person &p1, Person &p2){
    
    
	if(p1.m_Age == p2.m_Age){
    
    
		return p1.m_Hight < p2.m_Hight;
	}
	return p1.m_Age < p2.m_Age;
} 

void test01(){
    
    
	list<Person>L;
	
	Person p1("刘备", 35, 175);
    Person p2("曹操", 45, 180);
    Person p3("孙权", 40, 170);
    Person p4("赵云", 25, 190);
    Person p5("张飞", 35, 160);
    Person p6("关羽", 35, 200);
    
    L.push_back(p1);
    L.push_back(p2);
    L.push_back(p3);
    L.push_back(p4);
    L.push_back(p5);
    L.push_back(p6);
    
    for(list<Person>::iterator it = L.begin();it != L.end();it++){
    
    
		cout<< it->printInfo()<<endl;
    } 
    cout<<"----------------------------"<<endl; 
    L.sort(comparePerson);
    for(list<Person>::iterator it = L.begin();it != L.end();it++){
    
    
		cout<< it->printInfo()<<endl;
    }
    
}

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

 Para tipos de datos personalizados, debe especificar las reglas de clasificación; de lo contrario, no sabrá cómo ordenar. La
 clasificación avanzada consiste simplemente en especificar las reglas lógicas nuevamente en las reglas de clasificación, lo cual no es complicado.

2,8 juegos/contenedor multijuego

2.8.1 Concepto básico de conjunto

Introducción: todos los elementos se ordenarán automáticamente cuando se inserten
Esencia: set/multiset es un contenedor asociativo y la estructura subyacente se implementa con un árbol binario.
Diferencia: no se permiten elementos duplicados en el conjunto y se permiten elementos duplicados en el multiset

2.8.2 Construcción y asignación de conjuntos

Constructor:
set< T> st;//constructor predeterminado:
set(const set &st);//copiar constructor

Tarea:
set& operator=(const set &st);//Sobrecargar el operador de signo igual
Insertar datos:
insert();

set<int> s2(s1);
set<int> s3;
s3 = s2;

2.8.3 establecer el tamaño del contenedor e intercambiar

Prototipo de función:
size(); //devuelve el número de elementos en el contenedor
empty();//juzga si el contenedor está vacío
swap(st);//intercambia dos contenedores de colección

2.8.4 Establecer inserción y eliminación de contenedores

Prototipo de función:
insert(elem); // Insertar un elemento en el contenedor.
clear();//Borrar todos los elementos
erase(pos);//Eliminar el elemento señalado por el iterador pos y devolver el iterador del siguiente elemento.
erase(beg, end);//Elimina todos los elementos en el intervalo [inicio, fin) y devuelve el iterador del siguiente elemento.
erase(elem);//Elimina el elemento cuyo valor es elem en el contenedor.

s1.erase(s1.begin());
s1.erase(30);

2.8.5 establecer búsquedas y estadísticas

Prototipo de función: //Comprueba si la clave existe, si existe, devuelve el iterador
find(key); del elemento de la clave ; si no existe, devuelve set.end(); //Estadísticas del número de elementos clave, solo 0 o 1 para conjunto; puede ser mayor que 1 para conjunto múltiple;
count(key);

set<int>::iterator pos = s1.find(12);
if(pos != s1.end())
	cout << "找到元素" << endl;
else
	cout << "未找到元素" << endl;

2.8.6 Diferencia entre conjunto y multiconjunto

la diferencia:

 Set no puede insertar datos duplicados, mientras que multiset puede
 insertar datos con set y devolver el resultado de la inserción, indicando si la inserción fue exitosa.
 Multiset no detectará datos, por lo que se pueden insertar datos duplicados.

2.8.7 Crear un par de pares

Introducción a la función:

Para los datos que aparecen en pares, se pueden devolver dos datos utilizando el grupo de pares, el primer dato es el primero y el segundo dato es el segundo;

Prototipo de función:

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

Ejemplo:

 //test func of pair
void test4() {
    
    
    pair<string, int> p(string("tom"), 20);
    cout << "name: " << p.first << " " << " age: " << p.second << endl;

    pair<string, int> p2 = make_pair("jerry", 10);
    cout << "name: " << p2.first << " " <<  " age: " << p2.second << endl;
}

2.8.8 Establecer clasificación de contenedores

 La regla de clasificación predeterminada del contenedor establecido es de pequeño a grande, y la regla de clasificación se puede cambiar usando el functor. El método de clasificación
 no se puede especificar después de ingresar los datos. El método de clasificación debe especificarse al crear

Ejemplo: cree una clase MyCompare, sobrecargue el operador de llamada de función y use el nombre de la clase como segundo parámetro al crear el contenedor establecido.

class myCompare{
    
    
public:
	bool operator()(int v1, int v2){
    
    
		return v1 > v2;
	}
};

set<int, myCompare>s1;
下面插入的时候就会按照从大到小排列


  
   

2.9 contenedor de mapas/multimapas

Contenedor de mapas C++ STL: se encontró un artículo muy bueno

(1) Concepto básico de mapa

Introducción:

 Todos los elementos del mapa son pares.
 El primer elemento del par actúa como índice para la clave (valor clave) y el segundo elemento es el valor (valor). Todos los
 elementos se ordenarán automáticamente según el valor clave del elemento.

Naturaleza:

 map/multimap es un contenedor asociativo y la estructura subyacente se implementa con un árbol binario

ventaja:

El valor se puede encontrar rápidamente según el valor clave.

La diferencia entre mapa y multi:

El mapa no permite elementos de valor clave duplicados en el contenedor.
El mapa múltiple permite elementos de valor clave duplicados en el contenedor.

otro

Para tipos de datos personalizados, el mapa debe especificar la intercalación, que es la misma que la del contenedor establecido;

(2) Mapear funciones comunes

Constructor

map<T1, T2> mp;		//map默认构造函数: 
map(const map &mp);	//拷贝构造函数

cesión e intercambio

map& operator=(const map &mp);//重载等号操作符
swap(mp);			//交换两个集合容器

operación de tamaño de mapa

size();//返回容器中元素的数目
empty();//判断容器是否为空

operación de inserción de mapa

¿Por qué no se recomienda el cuarto método?
 Si utiliza el cuarto método para encontrar una clave que no existe, se creará automáticamente un nuevo par clave-valor con un valor de cero; por lo tanto, al generar de esta manera, debe hacer asegúrese de que el par clave-valor ya exista

map.insert(...); 
	//往容器插入元素,返回pair<iterator,bool>
//1 map的四种插入方法
void MapInsert(map<int, int> &m) {
    
    
	//1 通过模板pair对组.返回一个对组对象.其中:对组对象的模板参1为:被插入容器的(此处为map)迭代器类型;模板参2为:布尔类型,用于判断是否插入成功.
	std::pair<map<int,int>::iterator,bool> pairIt = m.insert(std::pair<int,int>(1,1));
	if(pairIt.second == false){
    
    
		std::cout << "1 insert map failed" << std::endl;
		return;
	}

	//2 通过make_pair()函数.同样返回一个对组对象
	pairIt = m.insert(std::make_pair(2, 2));
	if (pairIt.second == false) {
    
    
		std::cout << "2 insert map failed" << std::endl;
		return;
	}

	//3 通过map模板类中的value_type()函数.同样返回一个对组对象
	pairIt = m.insert(map<int, int>::value_type(3, 3));
	if (pairIt.second == false) {
    
    
		std::cout << "3 insert map failed" << std::endl;
		return;
	}

	//4 下标法插入.注:map中,key不存在,以默认值0插入map;key存在,修改该key的值.
	m[4] = 4;
	m[5];//默认为0.
	std::cout << m[6] << std::endl;//下标打印时不存在的key会默认被初始化为0.且会被插入到map中

	//所以此时map中共有6个元素
}

borrar

clear();//删除所有元素
erase(pos);//删除pos迭代器所指的元素,返回下一个元素的迭代器。
erase(beg,end);//删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
erase(keyElem);//删除容器中key为keyElem的对组。

Buscar estadísticas

find(key);//查找键key是否存在,若存在,返回该键的元素的迭代器;
		  //若不存在,返回map.end();
count(keyElem);
		 返回容器中key为keyElem的对组个数。
		 对map来说,要么是0,要么是1。
		 对multimap来说,值可能大于1lower_bound(keyElem);//返回第一个key>=keyElem元素的迭代器。
upper_bound(keyElem);//返回第一个key>keyElem元素的迭代器。
equal_range(keyElem);//返回容器中key与keyElem相等的上下限的两个迭代器。

para ordenar

El contenedor del mapa está ordenado en orden ascendente de forma predeterminada. Utilice el functor para cambiar el método de clasificación del contenedor del mapa.

class myCompare{
    
    
public:
	bool operator()(int v1, int v2){
    
    
			//降序:
			return v1 > v2;
			//升序
			//return v1 < v2;
	}
};
map<int, int, myCompare>m;//降序排列

Supongo que te gusta

Origin blog.csdn.net/Stanford_sun/article/details/122673045
Recomendado
Clasificación