STL
C++ STL(标准模板库)是一套功能强大的 C++ 模板类。
STL从广义上分为:容器(container)算法(algorithm)迭代器(iterator)
STL的六大组件
- Container(容器) 各种基本数据结构,如vector、list、deque、set、map等,用来存放数据
- Algorithm(算法) 各种基本算法,如sort、find、copy、for_each…等
- Iterator(迭代器) 连接containers和algorithms
- Adapter(适配器) 可改变containers、Iterators或Function object接口的一种组件
- Function object(仿函数) :行为类似函数、可作为算法的某种策略。
- Allocator(分配器) 负责空间的配置与管理。
1.Vector
vector基本概念
功能:
- vector数据结构和数组非常相似,也称为单端数组
vector与普通数组区别:
- 不同之处在于数组是静态空间,而vector可以动态扩展
动态扩展:
- 并不是在原空间之后续接新空间,而是找更大的内存空间,然后将原数据拷贝新空间,释放原空间
- vector容器的迭代器是支持随机访问的迭代器
vector赋值操作
功能描述:
- 给vector容器进行赋值
函数原型:
-
vector& operator=(const vector &vec);
//重载等号操作符 -
assign(beg, end);
//将[beg, end)区间中的数据拷贝赋值给本身。 -
assign(n, elem);
//将n个elem拷贝赋值给本身。
示例:
#include <vector>
void printVector(vector<int>& v) {
for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
//赋值操作
void test01()
{
vector<int> v1; //无参构造
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
printVector(v1);
vector<int>v2;
v2 = v1;
printVector(v2);
vector<int>v3;
v3.assign(v1.begin(), v1.end());
printVector(v3);
vector<int>v4;
v4.assign(10, 100);
printVector(v4);
}
int main() {
test01();
system("pause");
return 0;
}
vector容量和大小
功能描述:
- 对vector容器的容量和大小操作
函数原型:
-
empty();
//判断容器是否为空 -
capacity();
//容器的容量 -
size();
//返回容器中元素的个数 -
resize(int num);
//重新指定容器的长度为num,若容器变长,则以默认值填充新位置。 //如果容器变短,则末尾超出容器长度的元素被删除。
-
resize(int num, elem);
//重新指定容器的长度为num,若容器变长,则以elem值填充新位置。 //如果容器变短,则末尾超出容器长度的元素被删除
实例:
#include <iostream>
#include <vector>
void test01()
{
//创建一个vector容器
std::vector<int> v;
//向容器中插入数据
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
std::cout << v.empty() << std::endl;
std::cout << v.size() << std::endl;
std::cout << v.capacity() << std::endl;
}
int main()
{
test01();
return 0;
}
vector插入和删除
功能描述:
- 对vector容器进行插入、删除操作
函数原型:
push_back(ele);
//尾部插入元素elepop_back();
//删除最后一个元素insert(const_iterator pos, ele);
//迭代器指向位置pos插入元素eleinsert(const_iterator pos, int count,ele);
//迭代器指向位置pos插入count个元素eleerase(const_iterator pos);
//删除迭代器指向的元素erase(const_iterator start, const_iterator end);
//删除迭代器从start到end之间的元素clear();
//删除容器中所有元素
#include <iostream>
#include <vector>
void printVector(std::vector<int>& v)
{
for (std::vector<int>::iterator it = v.begin(); it != v.end(); it++) {
std::cout << *it << " ";
}
std::cout << std::endl;
}
//插入和删除
void test01()
{
std::vector<int> v1;
//尾插
v1.push_back(10);
v1.push_back(20);
v1.push_back(30);
v1.push_back(40);
v1.push_back(50);
printVector(v1);
//尾删
v1.pop_back();
printVector(v1);
//插入
v1.insert(v1.begin(), 100);
printVector(v1);
v1.insert(v1.begin(), 2, 1000);
printVector(v1);
//删除
v1.erase(v1.begin());
printVector(v1);
//清空
v1.erase(v1.begin(), v1.end());
v1.clear();
printVector(v1);
};
int main()
{
test01();
return 0;
}
10 20 30 40 50
10 20 30 40
100 10 20 30 40
1000 1000 100 10 20 30 40
1000 100 10 20 30 40
vector数据存取
功能描述:
- 对vector中的数据的存取操作
函数原型:
at(int idx);
//返回索引idx所指的数据operator[];
//返回索引idx所指的数据front();
//返回容器中第一个数据元素back();
//返回容器中最后一个数据元素
#include <iostream>
#include <vector>
void test01()
{
std::vector<int> v;
for (int i = 0; i < 2; i++)
{
v.push_back(i);
}
for (int i = 0; i < 2; i++)
{
std::cout << v[i] << std::endl;
}
for (int i = 0; i < 2; i++)
{
std::cout << v.at(i) << std::endl;
}
std::cout << "vector front \t" << v.front() << std::endl;
std::cout << "vector back \t" << v.back() << std::endl;
};
int main()
{
test01();
return 0;
}
0
1
0
1
vector front 0
vector back 1
vector互换容器
功能描述:
- 实现两个容器内元素进行互换
函数原型:
swap(vec);
// 将vec与本身的元素互换
示例:
#include <vector>
void printVector(vector<int>& v) {
for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
void test01()
{
vector<int>v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
printVector(v1);
vector<int>v2;
for (int i = 10; i > 0; i--)
{
v2.push_back(i);
}
printVector(v2);
//互换容器
cout << "互换后" << endl;
v1.swap(v2);
printVector(v1);
printVector(v2);
}
void test02()
{
vector<int> v;
for (int i = 0; i < 100000; i++) {
v.push_back(i);
}
cout << "v的容量为:" << v.capacity() << endl;
cout << "v的大小为:" << v.size() << endl;
v.resize(3);
cout << "v的容量为:" << v.capacity() << endl;
cout << "v的大小为:" << v.size() << endl;
//收缩内存
vector<int>(v).swap(v); //匿名对象
cout << "v的容量为:" << v.capacity() << endl;
cout << "v的大小为:" << v.size() << endl;
}
int main() {
test01();
test02();
system("pause");
return 0;
}
vector预留空间
功能描述:
- 减少vector在动态扩展容量时的扩展次数
函数原型:
-
reserve(int len);
//容器预留len个元素长度,预留位置不初始化,元素不可访问。
vecor获取元素
容器:vector
算法:for_each
迭代器:vector<int>::interator
#include <iostream>
#include <vector>
#include <algorithm> // 标准算法头文件
using namespace std;
void myPrint(int val)
{
cout << val << endl;
}
void test01()
{
//创建一个vector容器
vector<int> v;
//向容器中插入数据
v.push_back(10);
v.push_back(20);
v.push_back(30);
v.push_back(40);
//通过迭代器访问容器中的数据
vector<int>::iterator itBegin = v.begin(); //起始迭代器 指向容器中的第一个元素
vector<int>::iterator itEnd = v.end(); //结束迭代器 指向容器中最后一个元素的下一个位置
//第一种遍历方式
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);
//利用auto关键字和:还有更简洁的写法
for(auto it: v)
{
cout << it << endl;
}
}
int main()
{
test01();
return 0;
}
vector存放自定义数据类型
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class Person{
public:
Person(string name, int age){
this->m_Name = name;
this->m_Age = age;
}
string m_Name;
int m_Age;
};
void test01()
{
vector<Person> v;
Person person1("zhangsan", 24);
Person person2("lisi", 25);
Person person3("wangerma", 26);
//向容器中添加数据
v.push_back(person1);
v.push_back(person2);
v.push_back(person3);
//遍历容器
for(vector<Person>::iterator it = v.begin(); it != v.end(); it++){
cout << "姓名:" << (*it).m_Name << "年龄:" << (*it).m_Age << endl;
cout << "姓名:" << it->m_Name << "年龄:" << it->m_Age << endl;
}
}
int main(){
test01();
return 0;
}
姓名:zhangsan年龄:24
姓名:zhangsan年龄:24
姓名:lisi年龄:25
姓名:lisi年龄:25
姓名:wangerma年龄:26
姓名:wangerma年龄:26
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class Person{
public:
Person(string name, int age){
this->m_Name = name;
this->m_Age = age;
}
string m_Name;
int m_Age;
};
void test01()
{
vector<Person *> v;
Person person1("zhangsan", 24);
Person person2("lisi", 25);
Person person3("wangerma", 26);
//向容器中添加数据
v.push_back(&person1);
v.push_back(&person2);
v.push_back(&person3);
//遍历容器
for(vector<Person *>::iterator it = v.begin(); it != v.end(); it++){
cout << "姓名:" << (*it)->m_Name << "年龄:" << (*it)->m_Age << endl;
}
}
int main(){
test01();
return 0;
}
map/ multimap容器
map基本概念
简介:
- map中所有元素都是pair
- pair中第一个元素为key(键值),起到索引作用,第二个元素为value(实值)
- 所有元素都会根据元素的键值自动排序
本质:
- map/multimap属于关联式容器,底层结构是用二叉树实现。
优点:
- 可以根据key值快速找到value值
map和multimap区别:
- map不允许容器中有重复key值元素
- multimap允许容器中有重复key值元素
map构造和赋值
功能描述:
- 对map容器进行构造和赋值操作
函数原型:
构造:
map<T1, T2> mp;
//map默认构造函数:map(const map &mp);
//拷贝构造函数
赋值:
map& operator=(const map &mp);
//重载等号操作符
示例:
#include <iostream>
#include <map>
void printMap1(std::map<int, int> m)
{
for(std::map<int, int>::iterator it = m.begin(); it != m.end(); it++)
{
std::cout << "key = " << (*it).first << " value = " << it->second << std::endl;
}
}
void printMap2(std::map<int, int> m)
{
for(auto it: m)
{
std::cout << "key = " << it.first << " value = " << it.second << std::endl;
}
}
int main()
{
std::map<int, int> m;
m.insert(std::pair<int, int>(1,10));
m.insert(std::pair<int, int>(2,20));
printMap1(m);
//拷贝构造函数
std::map<int, int> m2(m);
printMap1(m2);
}
key = 1 value = 10
key = 2 value = 20
key = 1 value = 10
key = 2 value = 20
map大小和交换
功能描述:
- 统计map容器大小以及交换map容器
函数原型:
size();
//返回容器中元素的数目empty();
//判断容器是否为空swap(st);
//交换两个集合容器
map插入和删除
功能描述:
- map容器进行插入数据和删除数据
函数原型:
insert(elem);
//在容器中插入元素。clear();
//清除所有元素erase(pos);
//删除pos迭代器所指的元素,返回下一个元素的迭代器。erase(beg, end);
//删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。erase(key);
//删除容器中值为key的元素。
示例:
#include <iostream>
#include <map>
void printMap(std::map<int, int> m)
{
for(auto it: m)
{
std::cout << "key = " << it.first << " value = " << it.second << std::endl;
}
}
int main()
{
std::map<int, int> m;
// 第一种插入方式
m.insert(std::pair<int, int>(1, 10));
// 第二种插入方式
m.insert(std::make_pair(2, 20));
// 第三种插入方式
m.insert(std::map<int, int>::value_type(3, 30));
//第四种插入方式,不建议使用这种插入,用途 可以利用key访问到value
m[4] = 40;
printMap(m);
//删除
m.erase(m.begin());
printMap(m);
m.erase(3);
printMap(m);
//清空
m.erase(m.begin(),m.end());
m.clear();
printMap(m);
}
3.deque容器
3.3.1 deque容器基本概念
功能:
- 双端数组,可以对头端进行插入删除操作
deque与vector区别:
- vector对于头部的插入删除效率低,数据量越大,效率越低
- deque相对而言,对头部的插入删除速度回比vector快
- vector访问元素时的速度会比deque快,这和两者内部实现有关
deque内部工作原理:
deque内部有个中控器,维护每段缓冲区中的内容,缓冲区中存放真实数据
中控器维护的是每个缓冲区的地址,使得使用deque时像一片连续的内存空间
3.3.3 deque赋值操作
功能描述:
- 给deque容器进行赋值
函数原型:
-
deque& operator=(const deque &deq);
//重载等号操作符 -
assign(beg, end);
//将[beg, end)区间中的数据拷贝赋值给本身。 -
assign(n, elem);
//将n个elem拷贝赋值给本身。
#include <iostream>
#include <deque>
void printDeque01(std::deque<int> d)
{
for (auto it:d)
{
std::cout << it << std::endl;
}
}
void printDeque02(std::deque<int> &d)
{
for(std::deque<int>::iterator it = d.begin(); it != d.end(); it++)
{
std::cout << *it << std::endl;
}
}
int main()
{
std::deque<int> d1;
for(int i; i < 10;i++)
{
d1.push_back(i);
}
printDeque01(d1);
// printDeque02(d1);
std::deque<int> d2(d1.begin(), d1.end());
printDeque01(d2);
std::deque<int> d3(10, 12);
printDeque01(d3);
std::deque<int> d4(d1);
printDeque01(d4);
}
3.3.4 deque大小操作
功能描述:
- 对deque容器的大小进行操作
函数原型:
-
deque.empty();
//判断容器是否为空 -
deque.size();
//返回容器中元素的个数 -
deque.resize(num);
//重新指定容器的长度为num,若容器变长,则以默认值填充新位置。 //如果容器变短,则末尾超出容器长度的元素被删除。
-
deque.resize(num, elem);
//重新指定容器的长度为num,若容器变长,则以elem值填充新位置。 //如果容器变短,则末尾超出容器长度的元素被删除。
3.3.5 deque 插入和删除
功能描述:
- 向deque容器中插入和删除数据
函数原型:
两端插入操作:
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位置的数据,返回下一个数据的位置
3.3.5 deque 插入和删除
功能描述:
- 向deque容器中插入和删除数据
函数原型:
两端插入操作:
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位置的数据,返回下一个数据的位置
3.3.6 deque 数据存取
功能描述:
- 对deque 中的数据的存取操作
函数原型:
at(int idx);
//返回索引idx所指的数据operator[];
//返回索引idx所指的数据front();
//返回容器中第一个数据元素back();
//返回容器中最后一个数据元素
3.6 queue 容器
3.6.1 queue 基本概念
概念:Queue是一种先进先出(First In First Out,FIFO)的数据结构,它有两个出口
队列容器允许从一端新增元素,从另一端移除元素
队列中只有队头和队尾才可以被外界使用,因此队列不允许有遍历行为
队列中进数据称为 — 入队 push
队列中出数据称为 — 出队 pop
3.6.2 queue 常用接口
功能描述:栈容器常用的对外接口
构造函数:
queue<T> que;
//queue采用模板类实现,queue对象的默认构造形式queue(const queue &que);
//拷贝构造函数
赋值操作:
queue& operator=(const queue &que);
//重载等号操作符
数据存取:
push(elem);
//往队尾添加元素pop();
//从队头移除第一个元素back();
//返回最后一个元素front();
//返回第一个元素
大小操作:
empty();
//判断堆栈是否为空size();
//返回栈的大小
示例:
#include <iostream>
#include <queue>
#include <string>
class Person
{
public:
Person(std::string name, int age)
{
this->name = name;
this->age = age;
}
std::string name;
int age;
};
int main()
{
//创建队列
std::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())
{
std::cout << "队头元素-- 姓名: " << q.front().name
<< " 年龄: "<< q.front().age << std::endl;
std::cout << "队尾元素-- 姓名: " << q.back().name
<< " 年龄:" << q.back().age << std::endl;
std::cout << std::endl;
//弹出队头元素
q.pop();
}
return 0;
}
4.string
本质:
- string是C++风格的字符串,而string本质上是一个类
string和char *区别:
- char *是一个指针
- string是一个类,类内部封装了char*,管理这个字符串,是一个char*型的容器
特点:
string类内部封装了很多成员方法
例如:查找find,拷贝copy,删除delete替换replace,插入insert
sring管理char*所分配到额内存,不用担心复制越界和取值越界等,由类内部进行负责。
string赋值操作
功能描述:
- 给string字符串进行赋值
赋值的函数原型:
string字符串拼接
- +=
- append
#include <iostream>
#include <string>
using namespace std;
int main(){
string str1 = "I LOVE";
string str2 = "GAME";
str1 += str2;
cout << "str1:" << str1 << endl;
str1.append(str2);
cout << "str1:" << str1 << endl;
}
str1:I LOVEGAME
str1:I LOVEGAMEGAME
string 字符串查找和替换
find从左往右查找,rfind从右往左找
replace
#include <iostream>
#include <string>
using namespace std;
//find
void test01(){
string str1 = "I LOVE";
int pos = str1.find("LO");
if(pos == -1){
cout << "not find" << endl;
}
else{
cout << "pos:" << pos << endl;
}
}
//replace
void test02(){
string str1 = "abcdef";
//从1号位置起三个字符,替换成"1111
str1.replace(1, 3, "1111");
cout << "str1:" << str1 << endl;
}
int main(){
test01();
test02();
}
pos:2
str1:a1111ef
string字符存取
- char& operator[](int n) //通过[]方式获取字符
- char& at(int n)
#include <iostream>
#include <string>
using namespace std;
void test01(){
string str1 = "abcdefg";
for(int i = 0;i < str1.size();i++){
cout << str1[i] << endl;
}
for(int i = 0;i < str1.size();i++){
cout << str1.at(i) << endl;
}
}
int main(){
test01();
}
string插入和删除
- insert 插入
- erase 删除
#include <iostream>
#include <string>
using namespace std;
void test01(){
string str1 = "abcdefg";
//insert
str1.insert(1, "haizei");
cout << str1 << endl;
//erase
str1.erase(1, 6);
cout << str1 << endl;
}
int main(){
test01();
}
ahaizeibcdefg
abcdefg
string子串
- substr
#include <iostream>
#include <string>
using namespace std;
void test01(){
string str1 = "abcdefg";
string sub_str = str1.substr(1,3);
cout << sub_str << endl;
}
int main(){
test01();
}
bcd