C++ STL容器使用秘籍:map、set、vector选择与应用指南
发布时间: 2024-10-22 05:59:25 阅读量: 31 订阅数: 22
![C++ STL容器使用秘籍:map、set、vector选择与应用指南](https://iq.opengenus.org/content/images/2019/10/disco.png)
# 1. C++ STL容器概述
在C++标准模板库(STL)中,容器扮演着至关重要的角色。容器是能够存储一系列元素的数据结构,并提供了许多通用的方法来处理这些数据。STL容器能够支持快速查找、插入和删除等操作,并能方便地与其他库组件集成。
## 1.1 C++ STL容器的分类
STL容器大致可以分为两大类:序列容器和关联容器。
- **序列容器**:如`vector`, `deque`, `list`, `forward_list`, `array`,它们能够按照特定的顺序存储一系列元素,元素可以被访问和修改。
- **关联容器**:如`set`, `multiset`, `map`, `multimap`, `unordered_set`, `unordered_map`, `unordered_multiset`, `unordered_multimap`,这些容器内部通常通过平衡二叉树(如红黑树)或哈希表实现,支持高效的数据检索、插入和删除。
## 1.2 容器的基本特性
不同类型的容器具有不同的性能特点,例如:
- `vector`在尾部进行插入和删除操作效率很高,但在中间或头部插入和删除效率较低。
- `list`支持在任何位置高效插入和删除,但不支持随机访问。
- `map`和`set`提供快速的查找能力,并且能自动保持数据的排序状态。
## 1.3 选择合适的容器
选择合适的容器通常取决于数据的使用模式和性能需求。例如,如果你需要频繁地访问随机位置的元素,`vector`或`deque`可能是合适的选择。而对于需要自动排序的数据集合,`set`或`map`将是更好的选择。
```cpp
#include <iostream>
#include <vector>
#include <set>
int main() {
// 示例:创建和使用vector和set
std::vector<int> vec = {1, 2, 3, 4, 5};
std::set<int> st = {3, 4, 5, 6, 7};
// 输出vector中的元素
for (int num : vec) {
std::cout << num << ' ';
}
std::cout << std::endl;
// 输出set中的元素
for (int num : st) {
std::cout << num << ' ';
}
std::cout << std::endl;
return 0;
}
```
通过以上代码示例,我们可以看到如何在C++中创建和操作基本的STL容器。在接下来的章节中,我们将深入探讨各个容器的细节、使用方法以及在实际编程中的应用。
# 2. 深入理解map容器
## 2.1 map容器的基本概念与使用
### 2.1.1 map的定义和特性
在C++标准模板库(STL)中,map是一个非常重要的容器,它能够存储键值对(key-value pairs)。每个键值对由一个键(key)和一个与之对应的值(value)组成。map的主要特性是:
- map中的键必须是唯一的,不允许重复。
- map会根据键的大小自动排序,自动维护一个由键的顺序关系。
- map的键是const属性,即键是不可修改的。
- map的插入和删除操作的平均时间复杂度为O(log n)。
在C++11及以后的版本中,map提供了双向迭代器(BidirectionalIterator),支持前向和后向遍历。
map的使用场景广泛,特别适用于需要维护数据的有序性,并且需要根据键快速定位元素的场景。
### 2.1.2 map的初始化与赋值
map容器可以通过多种方式来初始化,例如:
```cpp
#include <iostream>
#include <map>
int main() {
// 方式1:默认构造函数
std::map<std::string, int> mymap;
// 方式2:复制构造函数,复制其他map对象
std::map<std::string, int> mymap2(mymap);
// 方式3:通过范围构造函数,复制已有的键值对
std::map<std::string, int> mymap3 = {{"apple", 1}, {"banana", 2}, {"cherry", 3}};
// 方式4:通过初始化列表
std::map<std::string, int> mymap4{{"orange", 4}, {"pear", 5}, {"watermelon", 6}};
// 方式5:通过赋值操作符
mymap = mymap4;
return 0;
}
```
赋值操作也很简单,可以直接使用等号将一个map赋值给另一个map,这会复制其所有键值对。
## 2.2 map容器的高级操作
### 2.2.1 迭代器的使用
map容器提供了迭代器来遍历其内部存储的元素。迭代器使用起来类似于指针。
```cpp
#include <iostream>
#include <map>
int main() {
std::map<std::string, int> mymap = {{"apple", 1}, {"banana", 2}, {"cherry", 3}};
// 获取map的迭代器
for(std::map<std::string, int>::iterator it = mymap.begin(); it != mymap.end(); ++it) {
std::cout << "Key: " << it->first << " Value: " << it->second << '\n';
}
return 0;
}
```
这段代码会输出map中的所有键值对。迭代器使得map可以在不改变其内部结构的前提下,高效地访问其元素。
### 2.2.2 关联函数对象
map允许用户定义比较函数来决定键值对的排序规则。通过模板参数,map可以接受自定义的比较函数对象。
```cpp
#include <iostream>
#include <map>
#include <functional>
// 自定义比较函数
struct MyCompare {
bool operator()(const std::string& lhs, const std::string& rhs) const {
return lhs < rhs;
}
};
int main() {
// 使用自定义比较函数构造map
std::map<std::string, int, MyCompare> mymap = {{"apple", 1}, {"banana", 2}, {"cherry", 3}};
// 遍历map
for(auto &p : mymap) {
std::cout << "Key: " << p.first << " Value: " << p.second << '\n';
}
return 0;
}
```
## 2.3 map容器在实践中的应用案例
### 2.3.1 数据库索引模拟
map可以用于模拟数据库中索引的存储结构。例如,在一个数据库表中,每个记录都有一个唯一的标识符,可以通过这个标识符快速访问记录。
```cpp
#include <iostream>
#include <map>
#include <string>
// 模拟数据库记录
struct Record {
int id;
std::string name;
int age;
};
// 使用map模拟数据库索引
std::map<int, Record> database;
int main() {
// 创建记录并插入到map中
Record r1 = {1, "Alice", 24};
database.insert(std::make_pair(r1.id, r1));
// 根据id检索记录
if(database.find(1) != database.end()) {
std::cout << "Record found: " << database[1].name << '\n';
}
return 0;
}
```
在这个例子中,map使用记录的id作为键,记录本身作为值,实现了一个简单的索引。
### 2.3.2 排序和去重
map可以用来进行排序和去重,因为它会自动根据键值对的键来排序。
```cpp
#include <iostream>
#include <map>
#include <vector>
int main() {
// 一个未排序且包含重复值的向量
std::vector<int> v = {5, 7, 3, 5, 2, 7};
// 创建一个map来存储元素和出现的次数
std::map<int, int> m;
// 遍历向量,将元素作为键存储在map中,如果键已存在,则增加其计数
for(int num : v) {
m[num]++;
}
// 输出排序后的结果
for(auto &p : m) {
std::cout << p.first << " is repeated " << p.second << " times.\n";
}
return 0;
}
```
此代码示例展示了如何使用map来对整数数组中的元素进行排序和计数,同时去除重复的元素。
# 3. 探索set容器的奥秘
set容器是C++ STL(标准模板库)提供的一个容器,它允许存储唯一元素,并自动根据这些元素的值对它们进行排序。set的内部实现通常是红黑树(一种自平衡二叉查找树),这意味着set容器能够以对数时间复杂度进行查找、插入和删除操作。set容器非常适用于需要快速查找并且不希望有重复元素的场景。
## set容器的理论基础
### set的特点和操作方式
set容器的特点包括:
- 所有元素都是唯一的。
- 元素自动排序,可以保证按照一定顺序进行迭代。
- 操作是高效的,特别是当元素数量较大时。
操作方式主要涉及到:
- 插入元素(insert)
- 删除元素(erase)
- 访问元素(通过迭代器)
- 查找
0
0