Standard Template Library (STL)
$1. Algorithms
<bits/stdc++>
怎么包含?
MingW中:E:\MinGW\lib\gcc\mingw32\8.2.0\include\c++\mingw32\bits,由于有两个bits文件夹,必须选择这一个才行,另外一个不包含stdc++.h这个文件。
QT中:安装带有C和C++的各种运行环境,在以后使用到的时候可以直接在QT的安装文件夹中直接搜索就可以,
E:\Qt\Tools\mingw730_64\lib\gcc\x86_64-w64-mingw32\7.3.0\include\c++\x86_64-w64-mingw32\bits.
将以上两个得到的bits文件夹复制到VS的include文件夹中就可以:
D:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.23.28105\include.
1. Sorting
The complexity of it is O(N*log(N)).
- sort (start_address, end_address)
start_address: the address of the first element of the array
and_address: the address of the next contigunous location of the last element of the array
- Acctually sort() sorts in the range of [start_address, end_address)
#include <iostream>
#include <algorithm>
using namespace std;
void show(int a[])
{
for (int i = 0; i < 10; i++)
{
cout << a[i] << " ";
}
}
int main()
{
int a[10] = {1, 5, 8, 9, 6, 7, 3, 4, 2, 0};
cout << "The array before sorting is: ";
show(a);
sort(a, a+10);
cout << "\n\nThe array after sorting is: ";
show(a);
return 0;
}
2. Binary Search
- binary_search(start_address, end_address, value_to_find)
start_address: the address of the first element of the array.
end_address: the address of the last element of the array.
value_to_find: the target value which we have to search for.
- Range: binary_search[start_address, end_address]
/**
*CPP program to implement Binary Search in STL
*/
#include <iostream>
#include <algorithm>
using namespace std;
void show(int a[], int ary_size)
{
for (int i = 0; i < ary_size; i++)
{
cout << a[i] << " ";
}
}
int main()
{
int a[] = { 1, 5, 8, 9, 6, 7, 3, 4, 2, 0 };
int asize = sizeof(a) / sizeof(a[0]);
cout << "The array is: ";
show(a, asize);
sort(a, a + asize);
show(a, asize);
if (binary_search(a, a + asize, 2))
{
cout << "\n2 is in array!" << endl;
}
else
{
cout << "Not found 2 in array!" << endl;
}
if (binary_search(a, a + asize, 10))
{
cout << "Find 10!" << endl;
}
else
{
cout << "Not found 10!" << endl;
}
return 0;
}
$2. Containers
实现了数据类型和算法的分离
1. pair
Link: Pair in C++ STL
Syntax: pair(data_type1, data_type2) Pair_name;
// CPP program to illustrate pair in STL
#include <iostream>
#include <utility>
using namespace std;
int main()
{
pair<int, string> PAIR1;
PAIR1.first = 3;
PAIR1.second = "three";
cout << PAIR1.first << " " << PAIR1.second << endl;
return 0;
}
2. vector容器
动态数组:容器存放的元素是按值复制的方式进行,所以如果是类的话,就必须提供拷贝构造函数,从而保证对象间的拷贝正常
- Iterators
begin() – Returns an iterator pointing to the first element in the vector.
end() – Returns an iterator pointing to the theoretical element that follows the last element in the vector.
rbegin() – Returns a reverse iterator pointing to the last element in the vector (reverse begining). It moves from last to first element.
rend() – Returns a reverse iterator pointing to the theoretical element preceding the first element in the vector (considered as reverse end).
cbegin() – Returns a constant iterator pointing to the first element in the vector.
cend() – Returns a constant iterator pointing to the theoretical element that follows the last element in the vector.
crbegin() – Returns a constant iterator pointing to the last element in the vector (reverse begining). It moves from last to first element.
cend() – Returns a constant reverse iterator pointing to the theoretical element preceding the first element in the vector (considered as reversed end).
- Capacity
size()
max_size() – Returns the maximum number of the elements that the vector can hold.
capacity() – Returns the size of the storage space currently allocated to the vector expressed as number of elements.
resize(n) – Resize the container so that it contains ‘n’ elements.
empty()
shrink_to_fit() – Reduces the capacity of the container to fit its size and destroys all elements beyond the capacity.
reverse() – Request that the veator capacity be at lease enough to contain n elements.
- push_back(num):将输入的num装进vector中,在尾部添加元素
vector<int> v(10); // 没有写初始值,默认初始化为0
v.push_back(100); // 在10个0的后面添加100
v.push_back(200); // 在100的后面添加200
- size()函数:获得vector的长度
- back():获取vector的尾部元素
- pop_back():删除vector的尾部元素
while (v.size() > 0)
{
v.back() = 66; // 修改尾部元素的值
cout << v.back() << endl;
v.pop_back();
}
- front():获取头部元素
- 修改头部元素的值:v.front() = 12;
- 函数返回值当左值,应该返回一个引用
- 通过数组的方式
// 写10的目的是:提前把内存准备好,不然会报错,无法通过下标访问元素:v[i]
vector<int> v(10, 0); // 定义10个int大小的空间,并将所有的元素初始化为0
for (int i = 0; i < 10; i++)
{
int temp;
cin >> temp;
v[i] = temp; // 如果没有提前定义多少个大小的空间,无法通过下标进行访问
}
- 通过迭代器进行vector的遍历
vector<int> v(10);
for (int i = 0; i < 10; i++)
{
v[i] = i + 1;
}
// 【说明】:当it == v.end()的时候,说明已经遍历完vector
// 即v.end()指向的是vector最后一个元素的下一个虚拟的位置,只是用来标记结束位置的
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << endl;
}
- vector中元素的插入:
- v.insert(v.begin(), 100);
- v.insert(v.end(), 200);
3. string类
string的用法
-
string的初始化
-
string的遍历
- 像字符数组一样操作,通过下标进行遍历
- 通过迭代器进行遍历
- at,s.at(i),区别在于at(i)可以捕获异常,在发生异常的时候(比如说数组越界的时候),at()能够捕获异常并继续运行,而直接通过下标进行索引的程序会被直接中断。
-
string和其他字符类型的转换:
- string --> char *, string s = “string”, char *str = s.c_str()
- char * --> string, char *str = “string”, string s(str);
-
string字符串的连接:
- 直接用"+"进行连接
- 使用string类自带的append()函数,s.append(s2)
-
string字符串中查找子串:
- find()函数:int index = s.find(“demo”, 0); // 从0开始查找,第一次出现"demo"的下标索引,下标从0开始的。
-
string中对指定的字符串进行替换:
- replace(ofindex, 3, “AAA”);
-
insert(0, “AAA”), insert(s.length(), “123”);
-
erase()
-
transform(s.begin(), s.end(), s.begin(), 函数)
即:操作的起始位置,操作完成后返回的字符串放置的位置,要对字符串进行操作的函数。
其中函数可以是:
- 函数的入口地址
- 函数对象
- 预定义的函数对象:比如toupper(所有的字母转换为大写),tolower
-
length()函数:获取string的长度
4. iterator迭代器
【定义】:迭代器是一个“可遍历STL容器内全部或部分元素”的对象
- 迭代器指出容器中的一个特定的位置
- 迭代器就如同一个指针
- 迭代器提供对一个容器中的对象的访问方法,并且可以定义容器中对象的范围
- 分类
- 输入迭代器:只写迭代器,往容器中写入元素,只能一次写入一个元素向前移动,只支持一遍算法,同一个迭代器不能两遍遍历一个序列
- 输出迭代器:只读迭代器
- 正向迭代器
- 双向迭代器
- vector与迭代器的配合使用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ArGVAXVC-1573288689324)(C:\Users\Xie Bailian\AppData\Roaming\Typora\typora-user-images\1573277989291.png)]
-
元素的删除:【注意】:当删除迭代器所指向的元素时,erase删除元素后悔自动将迭代器加1,并返回下一个迭代器的位置:it = v.erase(it);
- 区间删除:
v.erase(v.begin(), v.begin() + 3);
- v.clear() 删除v中的所有元素
- 指定位置删除:
v.erase(v.begin()); // 删除头部元素
- 删除指定的元素:
for (vector<int>::iterator it = v.begin(); i != v.end();) { if (*it == n) { // 当删除迭代器所指向的元素时,erase删除元素后悔自动将迭代器加1,并返回下一个迭代器的位置 it = v.erase(it); } else { it++; } }
5. deque双端数组
- d.push_bacK()
- d.push_front()
- d.pop_back()
- d.pop_front()
- d.front()
- d.back()
- 查找元素对应的下标值:find(),返回一个迭代器
deque<int>::iterator it = find(d.begin(), d.end(), 33);
if (it != d.end())
{
cout << "33对应的下标是:" << distance(d.begin(), it) << endl;
}
else
{
cout << "没有找到值为33的元素!" << endl;
}
- distance(d.begin(), d.end())
- 头文件:
#include <algorithm>
- 头文件:
6. stack容器
-
s.empty()
-
s.pop()
-
s.top()
-
s.push()
-
s.size()
7. queue队列
-
q.push()
-
q.front()
-
q.pop()
-
q.empty()
8. list双向链表
【定义】:双向链表容器,可以进行高效的插入删除元素
- list不可以随机存取元素,因此不支持at(pos)和[]操作符,同时list的迭代器只能:it++ or it–,不能进行it += 5这种操作
- l.push_back()
- l.size()
- l.insert()
【说明】:list双向链表插入元素时:是将指定的位置的元素及其之后的元素后移,新插入的元素代替之前在这个位置的元素
【说明】: 1.list双向链表插入元素时:是将指定的位置的元素及其之后的元素后移,新插入的元素代替之前在这个位置的元素; 2.list的index从0开始的。
l.insert(6, 100); // 在下标6的位置处插入元素100
// 0 1 2 3 4 5 6 7
// 0 1 2 3 4 5 100 6 7
- l.clear() 删除list中的所有的元素
- l.erase[begin, end)
- 左闭右开!
- 【注意】l.erase(l.begin(), l.begin() + 3)错误!不能使用begin() + 3,list不能随机存取元素!
- l.erase(pos)
- 删除pos位置的数据,返回下一个数据的位置
- l.remove(elem)
- 删除list容器中所有值与elem匹配的元素
9. priority_queue优先级队列
可分为最大值优先级队列(默认)和最小值优先级队列。
priority_queue<int> pq; // 默认情况下是最大值优先级队列
// 定义最小值优先级队列,less:提前定义好的预定义函数,谓词
priority_queue<int, vector<int>, less<int>> pq1;
priority_queue<int, vector<int>, greater<int>> pq2; // 定义最大值优先级队列
while (pq.size() > 0)
{
cout << pq.top() << endl;
pq.pop();
}
- push()
- pop()
- size()
- top()
10. set和multiset集合
set是一个集合容器,其中所包含的元素是唯一的,集合中的元素按照一定的顺序进行排列(默认递增)。
元素的插入过程是按照排序的规则进行插入的,因此不能指定插入的元素的位置。
set采用红黑树变体的数据结构实现,在插入和删除的操作上比vector快。
- set不可以直接存取元素:不能使用at.(pos)和[]操作符
- multiset与set的区别:
- set支持唯一的键值,每个元素只能出现一次
- multiset中,同一个值可以出现多次
- 不能够直接修改set或者multiset容器中的值(这类容器是自动进行排序的),如果要修改元素值,必须先删除原来的元素,再将修改值插入到容器中即可
- insert()
set<int> s; // 默认为递增
set<int, less<int>> s1; // 指定为递增
set<int, greater<int>> s2; // 指定为递减
// 删除set集合中的元素
while (!s.empty())
{
set<int>::iterator it = s.begin();
cout << *it << " ";
s.erase(s.begin()); // 删除当前元素,同时自动指向下一个元素
}
自定义的数据类型比较
仿函数的概念
class Student
{
private:
char name[20];
int age;
public:
Student(char *name, int age)
{
strcpy(this->name, *name);
this->age = age;
}
};
// 创建仿函数
struct FuncStudent
{
bool operator() (const Student &stu1, const Student &stu2)
{
// 定义递减规则
return stu1.age > stu2.age;
}
};
Student stu("dabai", 20);
set<Student, FuncStudent> s;
s.insert(stu);
// less和greater函数是已经定义好了的,可以直接使用,但只能够对基本的数据类型进行排序
- find(elem)
- 查找elem元素,返回指向elem元素的迭代器
- count(elem)
- 返回集合中elem元素的个数
- lower_bound(elem)
- 返回第一个>=elem元素的迭代器
- upper_bound(elem)
- 返回第一个>elem元素的迭代器
- equal_range(elem)
- 返回容器中与elem相等的上下限的两个迭代器,上限是闭区间,下限是开区间:[begin, end)
- 以上函数返回两个迭代器,被封装在pari中