目录
一、概述
二、容器
2.1 序列式容器
2.1.1、vector
2.1.2、deque
2.1.3、list
2.2、关联式容器
2.2.1、set
2.2.2、map
2.2.3、multimap
2.3、容器适配器
2.3.1、stack
2.3.2、queue
三、算法
3.1、find()
3.2、sort
3.3、transform
四、迭代器
C++ STL是指标准模板库(Standard Template Library),它是一个由函数模板和类模板组成的C++库。STL提供了大量的通用数据结构和算法,以方便程序员快速开发高质量的程序。
STL由三个部分组成:容器(Containers)、算法(Algorithms)和迭代器(Iterators)。
容器是STL的核心部分,它提供了一种管理和存储数据的方式。C++ STL中的容器可分为三类:序列式容器(Sequence Containers)、关联式容器(Associative Containers)和容器适配器(Container Adaptors)。
序列式容器是按照线性顺序存储数据的容器,其中最常用的是vector、deque和list。
vector是一个可变大小的数组,支持随机访问,即可以通过下标访问其中的元素。vector是一个高效的容器,其尾部添加或删除元素的操作复杂度为O(1),但在中间或头部添加或删除元素的操作需要移动其他元素,其复杂度为O(n)。
下面是一个vector的例子:
#include
#include
int main()
{
std::vector vec = {1, 2, 3, 4, 5};
vec.push_back(6);
for (int i = 0; i < vec.size(); ++i)
{
std::cout << vec[i] << " ";
}
return 0;
}
vector是一个动态数组,可以随时增加和删除元素,支持随机访问。vector的优点是支持快速的随机访问,可以在尾部插入和删除元素。缺点是在中间插入或删除元素时,需要移动后面的元素,效率较低。vector适合于元素数量比较少,需要随机访问的情况。
deque是一个双端队列,可以在头部和尾部快速添加和删除元素,支持随机访问,但其随机访问的效率不如vector。
下面是一个deque的例子:
#include
#include
int main()
{
std::deque deq = {1, 2, 3, 4, 5};
deq.push_front(0);
deq.push_back(6);
for (int i = 0; i < deq.size(); ++i)
{
std::cout << deq[i] << " ";
}
return 0;
}
deque的优点是既支持快速的随机访问,又支持在队列两端插入和删除元素。缺点是需要分配多个内存块来存储数据,对内存的使用比较浪费。deque适合于元素数量比较多,需要在队列两端插入和删除元素,同时需要随机访问元素的情况。
list是一个双向链表,支持在任意位置进行常数时间的插入和删除操作,但不支持随机访问。
下面是一个list的例子:
#include
#include
int main()
{
std::list li = {1, 2, 3, 4, 5};
li.push_front(0);
li.push_back(6);
for (auto it = li.begin(); it != li.end(); ++it)
{
std::cout << *it << " ";
}
return 0;
}
list的优点是在任意位置插入和删除元素时,效率很高。缺点是不能通过下标访问元素,只能通过迭代器访问元素。list适合于元素数量比较多,需要频繁地在中间插入和删除元素的情况。
关联式容器是按照键值(Key)排序存储数据的容器,其中最常用的是set和map。
set是一个集合,其中元素按照某种顺序排列,并且每个元素都是唯一的。插入、删除和查找操作的复杂度均为O(logn)。
下面是一个set的例子:
#include
#include
int main()
{
std::set s = {1, 2, 3, 4, 5};
s.insert(6);
for (auto it = s.begin(); it != s.end(); ++it)
{
std::cout << *it << " ";
}
return 0;
}
set的优点是可以快速地插入、删除和查找元素,并且元素是按照一定的顺序排列的。缺点是不能通过下标访问元素。set适合于需要按照一定的顺序存储元素,并且需要快速地插入、删除和查找元素的情况。
map是一个键值对的容器,每个键对应一个值,其中元素是由键值对(Key-Value Pair)组成的。插入、删除和查找操作的复杂度均为O(logn)。
下面是一个map的例子:
#include
#include
map的优点是可以快速地按照键进行查找、插入和删除操作。缺点是不能通过下标访问元素。map适合于需要存储键值对,并且需要快速地按照键进行查找、插入和删除操作的情况
multimap是一个键值对的容器,每个键可以对应多个值,可以快速地进行查找、插入和删除元素。
下面是一个multimap的例子:
#include
#include
容器适配器是一种特殊的容器,它们使用不同的数据结构来实现STL中的标准容器接口。常用的容器适配器有stack和queue。
stack是一种后进先出(Last-In-First-Out,LIFO)的数据结构,可以使用vector或deque来实现。
下面是一个stack的例子:
#include
#include
int main()
{
std::stack> s;
s.push(1);
s.push(2);
s.push(3);
while (!s.empty())
{
std::cout << s.top() << " ";
s.pop();
}
return 0;
}
queue是一种先进先出(First-In-First-Out,FIFO)的数据结构,可以使用deque来实现。
下面是一个queue的例子:
#include
#include
int main()
{
std::queue> q;
q.push(1);
q.push(2);
q.push(3);
while (!q.empty())
{
std::cout << q.top() << " ";
q.pop();
}
return 0;
}
STL中的算法是一个模板函数库,包括了大量的常用算法,如查找、排序、合并、查找、遍历等等。STL中的算法不依赖于具体的容器类型,因此可以在不同的容器中使用相同的算法函数。
STL中的算法函数都位于algorithm头文件中,可以通过#include
查找算法,用于在容器中查找指定的元素,返回指向该元素的迭代器,如果没有找到则返回容器尾后迭代器。
下面是一个find的例子:
#include
#include
#include
int main()
{
std::vector v = {1, 2, 3, 4, 5};
auto it = std::find(v.begin(), v.end(), 3);
if (it != v.end())
{
std::cout << "found " << *it << std::endl;
}
else
{
std::cout << "not found" << std::endl;
}
return 0;
}
排序算法,用于对容器中的元素进行排序,默认按照升序排序,也可以指定排序方式。
下面是一个sort的例子:
#include
#include
#include
int main()
{
std::vector v = {5, 3, 1, 4, 2};
std::sort(v.begin(), v.end());
for (auto it = v.begin(); it != v.end(); ++it)
{
std::cout << *it << " ";
}
return 0;
}
变换算法,用于对容器中的元素进行变换,可以将一个容器的元素复制到另一个容器中,并对其进行变换操作。
下面是一个transform的例子:
#include
#include
#include
int main()
{
std::vector v = {1, 2, 3, 4, 5};
std::vector v2;
std::transform(v.begin(), v.end(), std::back_inserter(v2), [](int x) { return x * x; });
for (auto it = v2.begin(); it != v2.end(); ++it)
{
std::cout << *it << " ";
}
return 0;
}
另外还有一些常用的算法函数:
reverse():对一个区间中的元素进行反转。
accumulate():对一个区间中的元素进行累加。
unique():在一个区间中删除相邻的重复元素。
count():统计一个区间中指定值的元素个数。
merge():将两个已排序的区间合并成一个已排序的区间。
迭代器是STL中的一个重要概念,它是一种通用的、抽象的指针类型,用于访问容器中的元素。通过使用迭代器,可以遍历容器中的元素,实现各种算法和操作。
STL中提供了五种迭代器类型:输入迭代器(Input Iterator)、输出迭代器(Output Iterator)、正向迭代器(Forward Iterator)、双向迭代器(Bidirectional Iterator)和随机访问迭代器(Random Access Iterator)。
stack和queue
不支持迭代器
下面是一些常用的迭代器函数:
begin():返回容器的起始位置的迭代器。
end():返回容器的结束位置的迭代器。
advance():使迭代器向前或向后移动指定的距离。
distance():计算两个迭代器之间的距离。
next():返回迭代器的下一个位置的迭代器。
prev():返回迭代器的前一个位置的迭代器。
下面是一个迭代器的例子:
#include
#include
int main()
{
std::vector v = {1, 2, 3, 4, 5};
for (std::vector::iterator it = v.begin(); it != v.end(); ++it)
{
std::cout << *it << " ";
}
return 0;
}