C++ STL learning (1) - container

C++ STL study notes (1) - container

trivia

 In order to prepare for the Blue Bridge Cup, I have to learn the C++STL part, which can save a lot of time; this note is to remember when watching the dark horse programmer's course on station B:

The ingenuity of dark horse programmers|C++ tutorial from 0 to 1 entry programming, learning programming is no longer difficult

1. Introduction to STL

1.1 Basic concepts of STL

  • STL (Standard Template Library, standard template library)
  • STL is broadly divided into: ① container (container) ② algorithm (algorithm) ③ iterator (iterator)
  • Containers and algorithms are connected through iterators
  • Almost all code in STL uses template classes or template functions

1.2 Six components of STL

STL is roughly divided into six types: containers, algorithms, iterators , functors, adapters (adapters), and space configurators.

  1. Containers: various data structures, such as vector, list, deque, set, map, etc., used to store data
  2. Algorithms: various commonly used algorithms, such as sort, find, copy, etc.
  3. Iterators: containers and algorithms Between the connector
  4. Functor: Behavior is similar to a function, as a certain strategy of the algorithm
  5. Adapter: used to modify the container or functor or iterator interface
  6. Space configurator: responsible for space configuration and management

1.3 Containers, Algorithms, Iterators in STL

1.3.1 Containers

Containers : Place data
 STL containers are some of the most widely used data structures. Commonly used
 data structures: arrays, linked lists, trees, queues, collections, and mapping tables.
 These containers are divided into two types : sequential containers and associative containers :
  sequential containers : Emphasis on the order of values, each element has a fixed position
  associative container : binary tree structure, there is no strict physical order relationship

1.3.2 Algorithms

Algorithm : limited steps to solve logical/mathematical problems
 Algorithms are divided into: qualitative change algorithm, non-qualitative change algorithm
 Qualitative change: algorithm that changes element content, delete copy
 non-qualitative change: operation does not change element content, counting search

1.3.3 Iterators

Iterators: Algorithms need to use iterators to access the data in the container
 Each container has its own iterator
用法类似于指针

Common iterator types are: bidirectional iterator, random access iterator

1.4 Introduction to Container Algorithm Iterator

 After understanding the concept of the STL container algorithm iterator, use the code to deepen the understanding
 of the most commonly used container: Vector , which can be understood as an array to demonstrate

1.4.1 vector stores built-in data types

 container: vector
 algorithm: for_each
 iterator: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 vector stores custom data types

(*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 vector container nested container

Learning objective: nest containers within containers, traverse all data output
example:

#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. STL commonly used containers

2.1 string container

2.1.1 Basic concept of string

Nature:

 - string是C++风格的字符串,而string本质上是一个类
The difference between string and char *:
 - char *是一个指针
 - string是一个类,类内部封装了char*,是char*型的容器

Features:

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

2.1.2 String constructor

Constructor prototype:

 - 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 String assignment operation

Function description:

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

assignment operation prototype function

赋值操作一共有两种:一种是直接用等号=,原型如下
 - 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;
}

Summary:
 There are many ways to assign values ​​to strings, but using operator= is a more practical method

2.1.4 String concatenation

Function description:

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

Function prototype:

 - 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

Summarize:

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

2.1.5 string search and replace

Function description:

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

Function prototype:

 - 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替换时要指定从哪儿个位置开始起,其后有多少个字符,替换成什么样的字符串。

  Tips: When C++ declares a function, followed by a const is to limit the function type to a constant member function, and a constant member function refers to a function that cannot change the value of a member variable. For example, "double d() const;", the "const" in it limits that the d() function cannot have any function to change the value of the member variable of the object to which it belongs, and if there is, an error will be reported at the compilation stage. Its main function is to make the meaning of member functions clearer. We can add const descriptions to the function prototypes of member functions that do not change the object. This form can be used when it is necessary to increase readability and reduce logic errors.

/*查找举例*/
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 Comparison of string strings

Compare by:

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

Function prototype:

在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;

Summarize:

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

2.1.7 string character access

There are two ways to access a single character in string

在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 string insertion and deletion

Function prototype:

在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")

Summarize

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

2.1.8 String substring acquisition

Function prototype:

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;
}

The following is the second type of container: vector

2.2 vector container

2.2.1 Basic concept of vector

Function:
  The vector data structure is very similar to an array, also known as a single-ended array .
The difference between a vector and an ordinary array :
  the difference is that an array is a static space, while a vector can be dynamically expanded
. Dynamic expansion:
  ① Instead of adding a new space after the original space, Instead, find a larger memory space, and then copy the original data to the new space to release the original space.
  ②The iterator of the vector container is an iterator that supports random access

2.2.2 vector constructor

Function prototype:

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 Vector assignment operation

Function prototype:

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

Example:

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

2.2.4 Vector capacity and size

Function prototype:

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

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

Example:

#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 vector insertion and deletion

Function prototype:

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() //删除容器中所有元素
Summary: Insert tail insertion, insert an element through an iterator, and insert an element in a range through an iterator; delete a tail deletion, delete an element through an iterator, and delete an element in a range through an iterator; empty the element.

Example:

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 Vector container data access

Function prototype:

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

Example:

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

2.2.6 vector swap container

Function prototype:

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

Example:

v1.swap(v2);

magical effect:

有一说一,这个里面的那个利用匿名对象来收缩空间的方法胎牛皮了!!!!!!
#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 vector reserved space

Function description:

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

Function prototype:

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

Example:

v.reserve(100000);


Below is the deque

2.3 deque container

2.3.1 Basic concept of deque container

characteristic:

Double-ended array, which can insert and delete operations on the head end.
The iterator of the deque container also supports random access.
When using it, you need to include the header file:#include<deque>

Difference from vector:

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

internalThe inner working principle of deque:

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

Central controller



2.3.2 deque constructor and iterator

Function prototype:

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

Example 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;

iterators:

When it is only for traversal without modification, it should be added that the container of constthe keyword type needs an iterator so that no error will be reported
constconst_iterator

Example 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 deque assignment operation

Function prototype:

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

Example:

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 deque size operation

Points to note:

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

Function prototype:

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

Summarize:

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

2.3.5 deque insertion and deletion

Function prototype:

 两端插入操作: 
 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位置的数据,返回下一个数据的位置

Example:

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

2.3.6 deque data access

Function prototype:

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

Example:

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

2.3.7 deque sorting

Notice:

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

algorithm:

sort(iterator beg, iterator end);

Example:

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


Below is the stack

2.4 stack container

2.4.1 Basic concept of stack

Concept: stack is a first in first out (first in first out) data structure,
  it has only one exit;
 only the top element of the stack can be accessed.
 stack does not provide traversal functions, nor does it provide iterators.
 Push- push
 Pop-pop
Alt

2.4.2 Stack common interface

Function prototype:

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

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

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

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

Example:

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


The following is queque

2.5 queue container

2.5.1 The basic concept of queque

concept:

Queue is a 先进先出(First In First Out, FIFO) data structure that has two exits. The queue
container allows adding elements from one end and removing elements from the other end.
Only the sum in the 队头 front()queue 队尾 back()can be used by the outside world, so the queue does not allow With traversal behavior,
the data in the queue is called— 入队 push
the data out of the queue is called—出队 pop
Alt

2.5.2 queque common interface

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

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

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

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

Summarize:

Entering the queue: push
Exiting the queue: pop
Returning the element at the head of the queue
Returning the element at the end of the queue: back
Judging whether the team is empty: empty
Returning the queue size: size

2.5.3 queque example

#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;
}


Below is the list

2.6 list

2.6.1 Basic concept of list

优缺点:

Advantages:
 Elements can be quickly inserted or deleted at any position;
Disadvantages:
 The traversal speed of the container is not as fast as the array;
 it takes up more space than the array;

STL中的链表

The linked list in STL is a two-way circular linked list, and the iterator only supports forward and backward movement, which belongs to双向迭代器
Alt

Summary: List and vector are the two most commonly used containers in STL , each with its own advantages and disadvantages.

2.6.2 list constructor

function prototype

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

Example:

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

3.7.3 list assignment and exchange

Function prototype :

  • assign(begin, end);//Assign the copy of the data in the range [beg, end) to itself.
  • assign(n, elem);// Assign n elem copies to itself
  • list& operator=(const list &lst);// Overload the equals operator
  • swap(lst);//Swap lst with its own elements.

example

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

3.7.4 list size operation

function prototype

size();//Return the number of elements in the container
empty();//Judge whether the container is empty
resize(num);//Respecify the length of the container as num, if the container becomes longer, fill the new position with the default value. If the container gets shorter, elements at the end that exceed the length of the container are removed.
resize(num, elem);//Respecify the length of the container as num. If the container becomes longer, fill the new position with the value of elem. If the container gets shorter, elements at the end that exceed the length of the container are removed.

#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 list insertion and deletion

Function prototype:

* 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 list data access

Function prototype:

l.front();Returns the first element of the container
l.back();Returns the last element of the container
Note:

Cannot use [] to access the elements in the list container
Can not use at() to access the elements of the list container
The reason is: the list is essentially a linked list, which is not suitable for storing data in continuous linear space, and the iterator does not support random access (it = it+1 error) , supports bidirectional access (it–)

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

2.7.7 List inversion and sorting

Function prototype:

reverse();Flip linked list
sort()sorting (member function, default ascending order, functor can be used to implement descending order)

important hint:

All containers that do not support random access iterators cannot use standard algorithms.
Containers that do not support random access iterators will provide some algorithms internally. The
sorting algorithm that comes with the list defaults to ascending order from small to large. Callback function or functor to implement descending order (callback function here)

/*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 List sorting case

#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;
}

 For custom data types, you must specify the sorting rules, otherwise you don’t know how to sort
 Advanced sorting is just to specify the logical rules again on the sorting rules, which is not complicated

2.8 set/multiset container

2.8.1 Basic concept of set

Introduction: All elements will be automatically sorted when inserted
Essence: set/multiset is an associative container, and the underlying structure is implemented with a binary tree.
Difference: Duplicate elements are not allowed in set, and duplicate elements are allowed in multiset

2.8.2 Set construction and assignment

Constructor:
set< T> st;//default constructor:
set(const set &st);//copy constructor

Assignment:
set& operator=(const set &st);//Overload the equal sign operator
Insert data:
insert();

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

2.8.3 set container size and swap

Function prototype:
size(); //return the number of elements in the container
empty();//judging whether the container is empty
swap(st);//exchange two collection containers

2.8.4 Set container insertion and deletion

Function prototype:
insert(elem); //Insert an element in the container.
clear();//Clear all elements
erase(pos);//Delete the element pointed by the pos iterator and return the iterator of the next element.
erase(beg, end);//Delete all elements in the interval [beg, end), and return the iterator of the next element.
erase(elem);//Delete the element whose value is elem in the container.

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

2.8.5 set lookup and statistics

Function prototype: //Check whether the key exists, if it exists, return the iterator
find(key); of the element of the key ; if it does not exist, return set.end(); //Statistics of the number of key elements, only 0 or 1 for set ; Can be greater than 1 for multiset;
count(key);

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

2.8.6 Difference between set and multiset

the difference:

 Set cannot insert duplicate data, while multiset can
 insert data with set and return the insertion result, indicating whether the insertion is successful.
 Multiset will not detect data, so duplicate data can be inserted

2.8.7 Create a pair pair

Function introduction:

For the data that appears in pairs, two data can be returned by using the pair group, the first data is first, and the second data is second;

Function prototype:

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

Example:

 //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 Set container sorting

 The default sorting rule of the set container is from small to large, and the sorting rule can be changed by using the functor. The sorting method
 cannot be specified after the data is put in. The sorting method should be specified when creating

Example: Create a MyCompare class, overload the function call operator, and use the class name as the second parameter when creating the set container.

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

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


  
   

2.9 map/multimap container

C++STL map container: a very good article found

(1) Basic concept of map

Introduction:

 All elements in the map are pairs.
 The first element in the pair acts as an index for key (key value), and the second element is value (value). All
 elements will be automatically sorted according to the key value of the element

Nature:

 map/multimap is an associative container, and the underlying structure is implemented with a binary tree

advantage:

The value can be quickly found according to the key value

The difference between map and multi:

map does not allow duplicate key value elements in the container
multimap allows duplicate key value elements in the container

other

For custom data types, map must specify the collation, which is the same as the set container;

(2) Map common functions

Constructor

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

assignment and exchange

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

map size operation

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

map insert operation

Why is the fourth method not recommended?
 If you use the fourth method to find a key that does not exist, a new key-value pair will be created automatically with a value of zero; therefore, when outputting in this way, you should make sure that the key-value pair already exists up

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个元素
}

delete

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

Find Statistics

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相等的上下限的两个迭代器。

to sort

The map container is sorted in ascending order by default, use the functor to change the sorting method of the map container

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

Guess you like

Origin blog.csdn.net/Stanford_sun/article/details/122673045