C++学习笔记(四十二)——STL之堆操作算法
STL 算法分类:
类别 | 常见算法 | 作用 |
---|---|---|
排序 | sort 、stable_sort 、partial_sort 、nth_element 等 | 排序 |
搜索 | find 、find_if 、count 、count_if 、binary_search 等 | 查找元素 |
修改 | copy 、replace 、replace_if 、swap 、fill 等 | 修改容器内容 |
删除 | remove 、remove_if 、unique 等 | 删除元素 |
归约 | for_each 、accumulate 等 | 处理数据 |
合并 | merge 、set_union 、set_intersection 等 | 处理有序序列 |
排列组合 | next_permutation 、prev_permutation 等 | 生成排列 |
堆操作 | push_heap 、pop_heap 、make_heap 、sort_heap 等 | 处理堆 |
堆操作算法
STL 提供了一些堆操作算法,主要用于堆数据结构的管理和操作。
堆是一种完全二叉树,满足每个父节点的值大于或等于(或小于或等于)其子节点的性质,常用来实现优先队列。
STL 中的堆操作函数位于 <algorithm>
头文件中,支持最大堆和最小堆的操作。
算法名称 | 功能描述 | 时间复杂度 | 空间复杂度 | 适用场景 |
---|---|---|---|---|
make_heap | 将一个容器转换为堆 | O(n) | O(1) | 将一个无序数组转换为堆 |
push_heap | 向堆中插入元素并维持堆的性质 | O(log n) | O(1) | 向堆中插入新元素时使用 |
pop_heap | 从堆中删除最大元素,并维持堆的性质 | O(log n) | O(1) | 从堆中移除最大元素时使用 |
sort_heap | 对堆中的元素进行升序排序 | O(n log n) | O(1) | 从堆中提取所有元素并按升序排序 |
is_heap | 检查容器是否为堆 | O(n) | O(1) | 检查容器是否满足堆的性质 |
is_heap_until | 返回堆中第一个不符合堆性质的位置 | O(n) | O(1) | 查找堆中第一个无效位置 |
(1)make_heap
- 功能:将一个范围内的元素转换成一个堆(默认最大堆)。它的工作是将一个无序数组转换成一个合法的堆。
- 时间复杂度:O(n),其中
n
是元素的数量。 - 空间复杂度:O(1)。
示例:
#include <iostream>
using namespace std;
#include <vector>
#include <algorithm> // make_heapint main() {vector<int> vec = { 10, 20, 30, 5, 15, 40 };make_heap(vec.begin(), vec.end());// 输出堆的内容for (int val : vec){cout << val << " ";}cout << endl;system("pause");return 0;
}
注意:
make_heap
适用于,当需要将一个容器(如vector
)转换为堆时。
(2)push_heap
- 功能:将一个元素插入堆中,并确保堆的性质仍然被保持。它假定该元素已插入到容器的末尾,并会调整堆的结构。
- 时间复杂度:O(log n),其中
n
是堆的大小。 - 空间复杂度:O(1)。
示例:
#include <iostream>
using namespace std;
#include <vector>
#include <algorithm> // push_heapint main() {vector<int> vec = { 10, 20, 30, 5, 15 };make_heap(vec.begin(), vec.end()); // 初始堆vec.push_back(40); // 向堆中添加元素push_heap(vec.begin(), vec.end()); // 重新调整堆// 输出堆的内容for (int val : vec){cout << val << " ";}cout << endl;system("pause");return 0;
}
注意:
- 当新的元素加入到堆时,需要用到
push_heap
函数来维持堆结构。
(3)pop_heap
- 功能:从堆中删除最大(或最小)元素,并确保堆的性质仍然被保持。它将堆的根元素(最大或最小)与容器的最后一个元素交换,然后通过堆调整操作恢复堆结构。
- 时间复杂度:O(log n),其中
n
是堆的大小。 - 空间复杂度:O(1)。
示例:
#include <iostream>
using namespace std;
#include <vector>
#include <algorithm> // pop_heapint main() {vector<int> vec = { 40, 20, 30, 5, 15 };make_heap(vec.begin(), vec.end()); // 初始堆pop_heap(vec.begin(), vec.end()); // 移除最大元素(堆顶元素)vec.pop_back(); // 删除容器末尾的元素// 输出堆的内容for (int val : vec){cout << val << " ";}cout << endl;system("pause");return 0;
}
注意:
pop_heap
适用于,当需要从堆中移除最大(或最小)元素时。
(4)sort_heap
- 功能:对堆中的元素进行排序(升序排序),即将堆中的元素按字典序排列。
- 时间复杂度:O(n log n),其中
n
是堆中元素的数量。 - 空间复杂度:O(1)。
示例:
#include <iostream>
using namespace std;
#include <vector>
#include <algorithm> // sort_heapint main() {vector<int> vec = { 40, 20, 30, 5, 15 };make_heap(vec.begin(), vec.end()); // 初始堆sort_heap(vec.begin(), vec.end()); // 对堆排序// 输出排序后的堆内容for (int val : vec){cout << val << " ";}cout << endl;system("pause");return 0;
}
注意:
sort_heap
适用于,当需要从堆中提取所有元素并按升序排序时。
(5)is_heap
- 功能:检查容器是否符合堆的性质(即容器是否为一个有效的堆)。返回值是一个布尔值。
- 时间复杂度:O(n),其中
n
是堆中元素的数量。 - 空间复杂度:O(1)。
示例:
#include <iostream>
using namespace std;
#include <vector>
#include <algorithm> // is_heapint main() {vector<int> vec = { 40, 20, 30, 5, 15 };make_heap(vec.begin(), vec.end()); // 初始堆if (is_heap(vec.begin(), vec.end())){cout << "该容器是一个有效的堆" << endl;}else{cout << "该容器不是一个有效的堆" << endl;}system("pause");return 0;
}
注意:
is_heap
适用于,当需要检查容器是否为有效堆时。
(6)is_heap_until
- 功能:返回堆中第一个不满足堆性质的位置。如果容器是一个有效的堆,则返回容器的末尾迭代器;否则,返回第一个不符合堆性质的元素位置。
- 时间复杂度:O(n),其中
n
是堆中元素的数量。 - 空间复杂度:O(1)。
示例:
#include <iostream>
using namespace std;
#include <vector>
#include <algorithm> // is_heap_untilint main() {vector<int> vec = { 40, 20, 30, 5, 15 };make_heap(vec.begin(), vec.end()); // 初始堆auto it = is_heap_until(vec.begin(), vec.end());if (it == vec.end()){cout << "该容器是一个有效的堆" << endl;}else{cout << "该容器不是一个有效的堆,第一个无效的元素: " << *it << endl;}system("pause");return 0;
}
注意:
is_heap_until
适用于,当需要确定堆的有效性以及出现不符合堆性质的位置时。