在编程中,数据处理是个绕不开的坎,尤其是需要频繁查找、插入或者判断元素是否存在的时候。如果你还在用数组手动遍历,那可能真的有点“辛苦打工人”的感觉了。别怕,今天带你认识C++里的map
和set
,这俩工具不光能让你的代码更高效,还能让你写得优雅得像艺术家。
下面,我们直接开干。
什么是 map
和 set
?
简单来说, map
是一种键值对(key-value
)的数据结构,专门用来存储“一对一”的映射关系。比如,想记录每个学生的分数,map
就是你的好帮手。而 set
是一个集合,专门用来存储不重复的元素。想判断某个东西存不存在?set
一招搞定。
它们的共同点是:都基于平衡二叉树实现,查找、插入、删除的时间复杂度是 O(logN) 。这比暴力遍历数组的 O(N) 高效多了!
温馨提示: map
和 set
默认是有序的,也就是说,里面的元素会按照键值的顺序排列。如果你不关心顺序,可以用无序版本——unordered_map
和 unordered_set
,它们基于哈希表实现,速度更快。
用法一:map
的基本操作
先看看 map
是怎么用的吧。假设现在要记录一批学生的分数,我们直接写代码:
#include <iostream>
#include <map>
using namespace std;
int main() {
map<string, int> student_scores; // 定义一个 map,键是 string,值是 int
// 插入数据
student_scores[“Alice”] = 95;
student_scores[“Bob”] = 89;
student_scores[“Charlie”] = 92;
// 查找数据
cout << “Alice's score: ” << student_scores[“Alice”] << endl;
// 遍历数据
for (const auto &pair : student_scores) {
cout << pair.first << “: ” << pair.second << endl;
}
// 删除数据
student_scores.erase(“Bob”);
// 判断键是否存在
if (student_scores.find(“Bob”) == student_scores.end()) {
cout << “Bob is not in the record.” << endl;
}
return 0;
}
运行结果会是这样的:
Alice's score: 95
Alice: 95
Bob: 89
Charlie: 92
Bob is not in the record.
解释一下代码:
- 插入数据 :
student_scores[“Alice”] = 95
就是往 map
里加一条记录。如果键已经存在,值会被覆盖。 - 查找数据
- 遍历数据 :用
for
循环,pair.first
是键,pair.second
是值。 - 删除数据
- 判断存在 :
find()
方法返回一个迭代器,如果等于 end()
,说明没找到。
温馨提示: map
的 []
操作符有个坑,如果你访问一个不存在的键,它会自动插入一个默认值。比如 student_scores[“Dave”]
会插入一个值为 0 的键值对。避免这种情况,可以用 find()
先判断。
用法二:set
的基本操作
再来看 set
。假设我们有一批数字,想判断某个数字是否存在,同时去重。用 set
再合适不过了。
#include <iostream>
#include <set>
using namespace std;
int main() {
set<int> numbers; // 定义一个 set,存储 int 类型的数据
// 插入数据
numbers.insert(10);
numbers.insert(20);
numbers.insert(30);
numbers.insert(20); // 重复插入无效
// 查找数据
if (numbers.find(20) != numbers.end()) {
cout << “20 is in the set.” << endl;
}
// 遍历数据
for (int num : numbers) {
cout << num << “ ”;
}
cout << endl;
// 删除数据
numbers.erase(10);
// 判断是否为空
if (numbers.empty()) {
cout << “The set is empty.” << endl;
}
return 0;
}
运行结果如下:
20 is in the set.
10 20 30
解释一下代码:
- 插入数据 :
insert()
用来往集合里加东西,重复元素会自动去掉。 - 查找数据 :
find()
方法返回一个迭代器,找到返回位置,找不到返回 end()
。 - 遍历数据 :
set
里的元素是有序的,所以你遍历出来的顺序一定是从小到大的。 - 删除数据
- 判断空集合
温馨提示: set
不支持通过下标访问,因为它不是连续存储的结构。如果需要按位置访问,可以用 vector
或 deque
。
应用场景:用 map
和 set
解决实际问题
1. 统计单词出现次数
假设从一段文本中统计每个单词出现的次数,直接用 map
:
#include <iostream>
#include <map>
#include <sstream>
using namespace std;
int main() {
map<string, int> word_count;
string text = “hello world hello cpp”;
stringstream ss(text);
string word;
while (ss >> word) {
word_count[word]++;
}
for (const auto &pair : word_count) {
cout << pair.first << “: ” << pair.second << endl;
}
return 0;
}
结果是:
2. 判断数组是否有重复元素
用 set
可以快速判断数组里有没有重复值:
#include <iostream>
#include <set>
#include <vector>
using namespace std;
bool hasDuplicates(const vector<int> &nums) {
set<int> unique_nums;
for (int num : nums) {
if (unique_nums.find(num) != unique_nums.end()) {
return true; // 找到重复元素
}
unique_nums.insert(num);
}
return false;
}
int main() {
vector<int> nums = {1, 2, 3, 4, 5, 2};
if (hasDuplicates(nums)) {
cout << “Array has duplicates.” << endl;
} else {
cout << “No duplicates found.” << endl;
}
return 0;
}
结果是:
map
和 set
是 C++ 提供的强大工具,专治数据处理中的各种麻烦事。 高效查找、自动排序、不重复存储 ,这些你平时头疼的需求,它们全都能搞定。用好了,不光能让你的代码跑得更快,还能让你写得更轻松。
别再用数组手动查找了,试试 map
和 set
,效率提升立竿见影!