- 数据处理太麻烦?试试C++ map和set,轻松实现高效查找!

文摘   2024-12-24 10:02   浙江  

在编程中,数据处理是个绕不开的坎,尤其是需要频繁查找、插入或者判断元素是否存在的时候。如果你还在用数组手动遍历,那可能真的有点“辛苦打工人”的感觉了。别怕,今天带你认识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 是值。
  • 删除数据
     :erase() 方法可以删除指定键值对。
  • 判断存在
     :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 里的元素是有序的,所以你遍历出来的顺序一定是从小到大的。
  • 删除数据
     :erase() 删除指定元素。
  • 判断空集合
     :empty() 方法能判断集合是否为空。


温馨提示: 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;

}

结果是:


cpp: 1

hello: 2

world: 1

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;

}

结果是:


Array has duplicates.

5

小结

map 和 set 是 C++ 提供的强大工具,专治数据处理中的各种麻烦事。 高效查找、自动排序、不重复存储 ,这些你平时头疼的需求,它们全都能搞定。用好了,不光能让你的代码跑得更快,还能让你写得更轻松。


别再用数组手动查找了,试试 map 和 set,效率提升立竿见影!



椰子树的秘密
优质内容创作者
 最新文章