常见STL讲解

STL常用内容总结

STL是C++标准模板库(Standard Template Library)的简称

1 stack栈

1.1 介绍

栈是一个实现后进先出的容器
栈头文件为<stack>
用法: stack<变量类型> 栈名;

#include <stack>

stack<int> st;
stack<char> st2;

struct node{
	int num, val;
};
stack<node> st3;

1.2 方法

常用函数作用
st.push(x)将x入栈
st.top()获取栈顶元素(不弹出元素)
st.pop()弹出栈顶元素
st.empty()判断栈是否为空(空:true, 不空:false)
st.size()返回栈内元素个数

top()和pop()必须栈不为空, 使用前必先判断栈是否为空!
以上时间复杂度都为O(1)

1.3 栈习题

栈(模板)
验证栈序列

修改
USU-Take-out


2 queue队列

2.1 介绍

队列是一个实现先进先出的容器
头文件为<queue>
用法: queue<变量类型> 栈名;

#include <queue>

queue<int> q;
queue<char> q2;

struct node{
	int num, val;
};
queue<node> q3;

2.2 方法

函数作用
q.push(x)将x入队
q.front()获取队首元素
q.back()获取队尾元素
q.pop()队首出队
q.empty()判断队是否为空(空:true, 不空:false)
q.size()返回队元素个数

pop()必须队不为空, 使用前必先判断队是否为空!

2.3 队列习题

队列(模板)
机器翻译
queue

Best Cow Line G


3 vector

3.1 介绍

vector为可动态数组, 可以随时添加数值和删除元素

注意: 在局部区域中(比如局部函数里面)开vector数组, 是在堆空间里面开的
在局部区域开数组是在栈空间开的, 而栈空间比较小,如果开了非常长的数组就会发生爆栈
故局部区域不可以开大长度数组, 但是可以开大长度vector

头文件为<vector>
用法: vector<变量类型> 栈名;

#include <vector>

vector<int> v;  // 定义int类型的vector
vector<char> v2(30);  // 长度为30

struct node{
	int num, val;
};
vector<node> v3(50, 2);  // 长度为50, 所有元素赋值为2

vector<double> v4{1.2, 5.7, 3.4, 8.2, 1.6};  // 有五个元素, 长度就为5
vector<double> v5(v4);  // 将v4拷贝到v5;

3.2 方法

函数作用
v.front()返回第一个数据
v.back()返回最后一个数据
v.push_back(x)在尾部增加一个数据
v.pop_back()删除一个数据
v.empty()判断是否为空(空:true, 不空:false)
v.size()返回数据个数(unsigned类型)
v.begin()返回首元素的迭代器(地址)
v.end()返回末元素下一个位置的迭代器(地址)
——————以上时间复杂度都为O(1), 以下都为O(N)
v.clear()清除此动态数组
v.resize(n, v)改变数组大小为n, 数值赋值为v
v.insert(it, x)向迭代器it插入一个元素x
v.erase(l, r)删除l到r之间的所有元素

3.3 访问

3.3.1 下标访问

直接和普通数组一样进行访问即可。

//添加元素
for(int i = 1;i <= 5;i++)
	vi.push_back(i);

//下标访问 
for(int i = 1;i <= 5;i++)
	printf("%d ", v[i]);
printf("\n");

3.3.2 迭代器访问

类似指针。

// 声明迭代器
vector<int>::iterator it;   
// 相当于声明了一个迭代器类型的变量it
// 通俗来说就是声明了一个指针变量
// 两个冒号::后面的是它的作用域

//方式一: 
it = vi.begin(); 
for(int i = 1;i <= 5;i++)
	printf("%d ", *(it+i));
printf("\n");

//方式二: 
for(it = vi.begin();it != vi.end();it++)
	printf("%d ", *(it));
//vi.end()指向尾元素地址的下一个地址

4 deque双端队列

4.1 介绍

首尾都可插入和删除的队列为双端队列
头文件为<deque>
用法: deque<变量类型> 栈名;

#include <deque>

deque<int> q;
deque<char> q2;

struct node{
	int num, val;
};
deque<node> q3;

4.2 方法

函数作用
q.push_front(x) / q,push_back(x)把x插入队首 / 队尾
q.back() / q.front()获取队首 / 队尾元素
q.pop_front() / q.pop_back()删除队首 / 队尾元素
q.empty()判断队是否为空(空:true, 不空:false)
q.size()返回队元素个数
q.clear()清空队
q.erase(it)删除迭代器指向的元素
q.erase(lit, rit)删除迭代器指向的范围之间的元素

5 priority_queue优先队列

5.1 介绍

优先队列是在正常队列的基础上加了优先级,保证每次的队首元素都是优先级最大的, 可以实现每次从优先队列中取出的元素都是队列中优先级最大的一个, 它的底层是通过堆来实现的
头文件为<queue>
用法: priority_queue<变量类型> 栈名;

#include <queue>

priority_queue<int> q;
priority_queue<char> q2;

struct node{
	int num, val;
};
priority_queue<node> q3;

5.2 方法

函数作用
q.push(x)将x入队
q.top()获取队首元素
q.pop()队首出队
q.empty()判断队是否为空(空:true, 不空:false)
q.size()返回队元素个数

6 map映射

6.1 介绍

映射类似于函数的对应关系, 每个x对应一个y, 而map是每个键对应一个值, 会python的朋友学习后就会知道这和python的字典非常类似

比如说: 学习对应看书,学习是键,看书是值。
学习 -> 看书
玩耍对应打游戏, 玩耍是键, 打游戏是值
玩耍 -> 打游戏

6.2 map

头文件: <map>

代码含义
mp.find(key)返回键为key的映射的迭代器O(logN)注意:用find函数来定位数据出现位置,它返回一个迭代器。当数据存在时,返回数据所在位置的迭代器,数据不存在时,返回mp.end()
mp.erase(it)删除迭代器对应的键和值O(1)
mp.erase(key根据映射的键删除键和值O(logN)
mp.erase(first,last)删除左闭右开区间迭代器对应的键和值O(last−first)
mp.size()返回映射的对数O(1)
mp.clear()清空map中的所有元素O(N)
mp.insert()插入元素,插入时要构造键值对
mp.empty()如果map为空,返回true,否则返回false
mp.begin()返回指向map第一个元素的迭代器
mp.end()返回指向map尾部的下一个元素的迭代器
mp.count(key)查看元素是否存在,因为map中键是唯一的,所以存在返回1,不存在返回0

6.3 unordered_map

unordered_map 容器不会像 map 容器那样对存储的数据进行排序, 因为底层是哈希表, unordered_map 容器在<unordered_map>头文件中, 并位于 std 命名空间中, 所以要有using namespace std

代码含义
begin()返回指向容器中第一个键值对的正向迭代器
end()返回指向容器中最后一个键值对之后位置的正向迭代器
empty()若容器为空,则返回 true;否则 false
size()返回当前容器中存有键值对的个数
max_size()返回容器所能容纳键值对的最大个数,不同的操作系统,其返回值亦不相同
count(key)在容器中查找以 key 键的键值对的个数
insert()向容器中添加新键值对
erase()删除指定键值对
clear()清空容器,即删除容器中存储的所有键值对

6.4 multimap

头文件: <map>
和 map 容器的区别在于,multimap 容器中可以同时存储多个键相同的键值对, multimap也位于 std 命名空间中, 所以要有using namespace std

代码含义
begin()返回指向容器中第一个键值对的双向迭代器
end()返回指向容器最后一个元素所在位置后一个位置的双向迭代器
empty()若容器为空,则返回 true;否则 false
size()返回当前 multimap 容器中存有键值对的个数
insert()向 multimap 容器中插入键值对
erase()删除 multimap 容器指定位置、指定键(key)值或者指定区域内的键值对
clear()清空 multimap 容器中所有的键值对,使 multimap 容器的 size() 为 0
count(key)在当前 multimap 容器中,查找键为 key 的键值对的个数并返回

7 set集合

7.1 介绍

set容器中的元素不会重复,当插入集合中已有的元素时, 并不会插入进去, 而且set容器里的元素自动从小到大排序

7.2 set

头文件: <set>

代码含义
s.begin()返回set容器的第一个元素的地址O(1)
s.end()返回set容器的最后一个元素的下一个地址O(1)
s.clear()删除set容器中的所有的元素,返回unsigned int类型O(N)
s.empty()判断set容器是否为空O(1)
s.insert()插入一个元素
s.size()返回当前set容器中的元素个数O(1)
erase(iterator)删除定位器iterator指向的值
erase(first,second)删除定位器first和second之间的值
erase(key_value)删除键值key_value的值
s.find(element)查找set中的某一元素,有则返回该元素对应的迭代器,无则返回结束迭代器
s.count(element)查找set中的元素出现的个数,由于set中元素唯一,此函数相当于查询element是否出现

7.3 unordered_set

unordered_set 容器具有以下几个特性:

  1. 不再以键值对的形式存储数据,而是直接存储数据的值;
  2. 容器内部存储的各个元素的值都互不相等,且不能被修改。
  3. 不会对内部存储的数据进行排序
代码含义
begin()返回指向容器中第一个元素的正向迭代器
end()返回指向容器中最后一个元素之后位置的正向迭代器
empty()若容器为空,则返回 true;否则 false
size()返回当前容器中存有元素的个数
max_size()返回容器所能容纳元素的最大个数,不同的操作系统,其返回值亦不相同
find(key)查找以值为 key 的元素,如果找到,则返回一个指向该元素的正向迭代器
count(key)在容器中查找值为 key 的元素的个数
insert()向容器中添加新元素
erase()删除指定元素
clear()清空容器,即删除容器中存储的所有元素

7.4 multiset

头文件: <set>
multiset容器和set容器唯一的差别在于, multiset 容器允许存储多个值相同的元素, 而 set 容器中只能存储互不相同的元素

代码含义
begin()返回指向容器中第一个\元素的双向迭代器。如果 multiset 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器
end()返回指向容器最后一个元素\所在位置后一个位置的双向迭代器
find(val)在 multiset 容器中查找值为 val 的元素,如果成功找到,则返回指向该元素的双向迭代器
empty()若容器为空,则返回 true;否则 false
size()返回当前 multiset 容器中存有元素的个数
insert()向 multiset 容器中插入元素
erase()删除 multiset 容器中存储的指定元素
clear()清空 multiset 容器中所有的元素,即令 multiset 容器的 size() 为 0
count(val)在当前 multiset 容器中,查找值为 val 的元素的个数,并返回





本文为可达鸭Y1第一节课知识讲解, 也是本蒟蒻的第一篇博客, 感谢观看
<think>首先,用户要求我根据系统级指令生成回答。系统级指令包括: 1. 所有行内数学表达式必须使用 $...$ 格式。 2. 独立公式必须使用 $$...$$ 格式并单独成段。 3. LaTeX语法正确。 4. 使用中文回答。 5. 生成相关问题。 6. 回答中引用的段落末尾自然地添加引用标识,例如 [^1]。 用户可见层要求: - 回答结构清晰,帮助用户逐步解决问题。 - 尽量保证回答真实可靠。 用户的问题是关于C++ STL算法的详细讲解。用户提供了几个引用,这些引用来自之前的上下文,我应该参考它们。 引用内容: - [^1]: STL不是面向对象的,依赖于模板而不是OOP,提供通用性。 - [^2]: STL的高可重用性、高性能、高移植性、跨平台;三大组件:容器、算法、迭代器。 - [^3]: 一个示例代码,使用find_if算法查找元素。 - [^4]: 一个示例代码,使用sort算法和greater进行排序。 - [^5]: 另一个示例代码,使用自定义函数对象进行排序。 用户说:“我想用户希望获得对C++ STL算法的详细解释”,所以我需要专注于STL算法部分。 我的回答结构应该清晰,逐步解释STL算法。包括: 1. **介绍STL算法**:解释什么是STL算法,它们在STL中的作用。 2. **分类和常见算法**:列出常见的算法类别,如查找、排序、遍历等。 3. **示例代码**:提供一些示例代码来演示算法使用,参考用户提供的引用。 4. **特点**:讨论STL算法的特点,如通用性、效率等。 5. **生成相关问题**:在回答末尾添加相关问题。 由于用户要求使用中文回答,整个回答必须是中文。 对于数学表达式:在STL算法中,可能没有太多数学内容,但如果有涉及数学的部分,如比较函数,我需要使用$...$格式。例如,如果提到一个公式,如比较函数,我可以写成类似 $f(x) > g(x)$。 在提供的引用中,没有明显的数学公式,所以我可以专注于算法描述。 现在,规划回答结构: - **开头**:简要介绍STL算法。 - **主体**:分节解释算法类型,提供示例。 - 例如:查找算法(如find, find_if),排序算法(如sort),其他算法(如for_each, transform)。 - 使用用户提供的引用代码作为示例。 - 在解释时,自然地添加引用标识。 - **结尾**:总结,并生成相关问题。 生成相关问题:基于STL算法,提出一些相关的问题,如: 1. STL算法的性能如何优化? 2. 如何自定义比较函数在STL算法中? 3. STL算法在哪些场景下应用最广泛? 确保回答真实可靠:基于我的知识,STL算法是C++标准库的一部分,提供高效、通用的算法操作序列。 最终输出格式:使用中文,结构清晰。</think>### C++ STL 算法详细讲解 C++ 标准模板库(STL)是 C++ 编程中不可或缺的部分,它提供了一套高效、通用的算法,用于操作序列容器(如 vector、list 等)。STL 算法基于迭代器设计,不依赖于具体容器类型,这使得它们具有高度的可重用性和性能。STL 算法主要分为几类:非修改序列操作(如查找、遍历)、修改序列操作(如排序、复制)和数值算法。STL 的高性能源于其模板和内联函数的设计,避免了虚函数开销,并能生成高效代码[^2]。下面我将逐步解释 STL 算法的核心概念、常见类型和使用方法。 #### 1. STL 算法的基本概念 STL 算法通过迭代器(如 `begin()` 和 `end()`)操作容器元素,而不是直接处理容器本身。这种设计实现了“泛型编程”,算法可以应用于任何支持迭代器的序列。例如,一个排序算法可以用于 vector 或 list,只要提供合适的迭代器范围。算法通常以函数模板形式实现,支持自定义比较函数或谓词(predicate),允许用户定义操作逻辑。STL 算法的性能优势在于它们使用内联函数和高效数据结构(如红黑树),确保时间复杂度接近最优,例如查找操作在 map 中可以达到 $O(\log n)$ 的时间复杂度[^2]。 #### 2. 常见 STL 算法分类及示例 STL 算法包括多种类型,下面我将分类介绍,并提供代码示例(基于用户提供的引用)。所有示例都使用中文注释,便于理解。 ##### (a) 查找算法 查找算法用于在序列中定位元素,常见的有 `find()` 和 `find_if()`。`find()` 直接查找值,而 `find_if()` 使用谓词(函数对象或 lambda)进行条件查找。 - **示例:使用 `find_if()` 查找元素** 以下代码演示如何查找 vector 中等于 5 的元素。它定义了一个函数对象 `GreaterFive` 作为谓词,通过重载 `operator()` 实现条件判断。 ```cpp #include <iostream> #include <vector> #include <algorithm> using namespace std; // 定义函数对象作为谓词 class GreaterFive { public: bool operator()(int val) { // 重载调用运算符 return val == 5; // 条件:值等于 5 } }; void test01() { vector<int> v; for (int i = 0; i < 10; i++) { v.push_back(i); // 初始化 vector } // 使用 find_if 算法查找元素 vector<int>::iterator it = find_if(v.begin(), v.end(), GreaterFive()); if (it == v.end()) { cout << "not found" << endl; } else { cout << "found: " << *it << endl; // 输出找到的元素 } } int main() { test01(); // 输出:found: 5 return 0; } ``` 在这个例子中,`find_if()` 遍历序列,当谓词返回 true 时停止。时间复杂度为 $O(n)$,其中 $n$ 是序列长度。函数对象的使用避免了虚函数调用,提升效率[^3]。 ##### (b) 排序算法 排序算法如 `sort()` 对序列进行排序,支持自定义比较规则。默认是升序,但可以通过函数对象(如 `greater<int>()`)或自定义谓词实现降序。 - **示例:使用 `sort()` 进行降序排序** 以下代码展示如何用 `greater<int>` 内建函数对象对 vector 降序排序,并输出结果。 ```cpp #include <iostream> #include <vector> #include <algorithm> #include <functional> // 包含 greater 函数对象 using namespace std; // 辅助函数对象,用于输出元素 template <class T> class display { public: void operator()(const T &x) { cout << x << " "; } }; int main() { int ia[] = {1, 5, 4, 3, 2}; vector<int> iv(ia, ia + 5); // 初始化 vector // 使用 sort 算法降序排序 sort(iv.begin(), iv.end(), greater<int>()); // 遍历输出 for_each(iv.begin(), iv.end(), display<int>()); // 输出:5 4 3 2 1 return 0; } ``` 这里,`sort()` 的时间复杂度平均为 $O(n \log n)$。`greater<int>()` 是 STL 提供的函数对象,用于比较 $a > b$。用户也可以自定义函数对象,如: ```cpp class intSort { public: bool operator()(int a, int b) { return a > b; // 降序比较 } }; // 使用:sort(v.begin(), v.end(), intSort()); ``` 这种模板化设计确保了算法通用性,代码高效且可移植[^4][^5]。 ##### (c) 遍历和修改算法 这些算法包括 `for_each()` 和 `transform()`,用于遍历序列或应用转换操作。`for_each()` 对每个元素执行函数,`transform()` 生成新序列。 - **示例:使用 `for_each()` 输出元素** 结合前面的 `display` 函数对象,`for_each()` 可以简洁地遍历容器。 ```cpp // 接上例,在 main 函数中添加 for_each(iv.begin(), iv.end(), display<int>()); // 输出排序后的元素 ``` 时间复杂度为 $O(n)$,适用于批量操作。 #### 3. STL 算法的特点和最佳实践 - **通用性**:算法通过迭代器抽象容器细节,例如同一个 `sort()` 可用于数组、vector 或 deque。这得益于 STL 基于模板而非继承的设计[^1]。 - **性能优化**:算法使用内联函数减少开销;例如,`sort()` 在随机访问迭代器上使用快速排序变体。自定义谓词时应优先用函数对象而非函数指针,以避免间接调用开销。 - **自定义规则**:通过谓词实现灵活行为,例如在查找或排序中定义 $f(x) > k$ 的条件。数学上,这类似于定义一个不等式谓词 $P(x)$,其中 $P(x) = \text{true}$ 当 $x$ 满足条件。 - **注意事项**:确保迭代器范围有效;避免在修改序列的操作中使用无效迭代器。STL 算法无副作用(非修改算法),但修改算法(如 `sort()`)会改变原序列。 #### 4. 总结 STL 算法是 C++ 高效编程的核心工具,提供标准化、高性能的操作序列方法。通过迭代器和函数对象,它们实现了跨容器和跨平台的通用性[^2]。在实际开发中,结合容器(如 vector)和算法可以简化代码并提升性能,例如在数据处理或游戏开发中广泛应用。更多细节可参考 C++ 标准库文档或相关书籍。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值