1. C++中的set和map容器详解
作为C++标准库中重要的关联容器,set和map在实际开发中有着广泛的应用。它们基于红黑树实现,提供了高效的查找、插入和删除操作。本文将深入探讨这两种容器的使用方法和底层原理。
1.1 set容器基础
set是C++标准库提供的一种关联容器,它存储唯一键值并按特定顺序排列。从底层实现来看,set通常基于红黑树(一种自平衡二叉搜索树)实现,这保证了元素的有序性和操作的高效性。
set的基本特性包括:
- 元素自动排序(默认升序)
- 不允许重复元素
- 查找、插入和删除操作的时间复杂度为O(log n)
cpp复制#include <iostream>
#include <set>
int main() {
std::set<int> mySet = {5, 2, 8, 1, 4};
// 自动排序且去重
for(int num : mySet) {
std::cout << num << " ";
}
// 输出: 1 2 4 5 8
}
1.2 set的模板参数解析
set的模板声明如下:
cpp复制template <class Key, class Compare = less<Key>, class Allocator = allocator<Key>>
class set;
三个模板参数分别代表:
- Key:存储元素的类型
- Compare:比较函数对象类型,默认为std::less
- Allocator:内存分配器类型,默认为std::allocator
我们可以通过自定义比较函数来改变元素的排序方式:
cpp复制#include <functional>
std::set<int, std::greater<int>> descendingSet = {5, 2, 8, 1, 4};
for(int num : descendingSet) {
std::cout << num << " ";
}
// 输出: 8 5 4 2 1
1.3 set的常用操作
1.3.1 插入元素
set提供了几种插入元素的方法:
cpp复制std::set<int> s;
// 方法1:直接插入值
s.insert(10);
// 方法2:使用emplace(C++11引入)
s.emplace(20);
// 方法3:插入一个范围
std::vector<int> vec = {30, 40, 50};
s.insert(vec.begin(), vec.end());
insert方法返回一个pair,其中first是指向插入元素的迭代器,second是一个bool值,表示是否成功插入(对于set,元素已存在时返回false)。
1.3.2 查找元素
set提供了多种查找方法:
cpp复制std::set<int> s = {10, 20, 30, 40, 50};
// 方法1:使用find
auto it = s.find(30);
if(it != s.end()) {
std::cout << "Found: " << *it << std::endl;
}
// 方法2:使用count
if(s.count(30)) {
std::cout << "30 exists in set" << std::endl;
}
// 方法3:使用lower_bound和upper_bound进行范围查找
auto low = s.lower_bound(20); // 第一个不小于20的元素
auto up = s.upper_bound(40); // 第一个大于40的元素
for(auto it = low; it != up; ++it) {
std::cout << *it << " "; // 输出: 20 30 40
}
1.3.3 删除元素
删除元素也有多种方式:
cpp复制std::set<int> s = {10, 20, 30, 40,
