C++中的pair map set 三者之间的联系与区别
联系:map 的元素类型实际上是 pair(键值对),其中键是唯一的,而 set 只存储唯一的键(可以认为是只有键没有值的 map)。 区别:pair 仅仅是一个将两个值绑定在一起的结构体,没有提供容器的功能。map 是一个键值对集合,每个元素都是一个 pair,通过键来访问值。set 只存储唯一的元素,不像 map 那样存储键值对。
pair
#include<bits/stdc++.h>
using namespace std;
int main() {
/*pair*/
pair<int, string> p = make_pair(1, "apple");
// 访问 pair 的元素
cout << "First: " << p.first << ", Second: " << p.second << endl;
// 修改 pair 的元素
p.first = 2;
p.second = "banana";
cout << "First: " << p.first << ", Second: " << p.second << endl;
return 0;
}
pair的赋值方式
使用构造函数
直接在创建 pair 对象时,通过构造函数传递值。
pair<int, string> p(1, "apple");
使用 make_pair
make_pair 是一个辅助函数,可以根据其参数自动推导出返回的 pair 对象的类型。
pair<int, string> p = make_pair(1, "apple");
列表初始化(C++11 及以上)
在 C++11 及更高版本中,你可以使用花括号 {} 进行列表初始化。
pair<int, string> p = {1, "apple"};
复制(拷贝)赋值
如果你已经有了另一个 pair<int, string> 对象,可以直接将其赋值给新对象。
pair<int, string> p1(1, "apple");
pair<int, string> p2 = p1; // p2 现在有了 p1 的所有值
移动赋值(C++11 及以上)
对于支持移动语义的对象,可以使用移动赋值来转移资源,这通常更高效。
pair<int, string> p1 = make_pair(1, "apple");
pair<int, string> p2 = move(p1); // 使用 p1 的资源,p1 被置于不确定但有效的状态
使用 tie(C++11 及以上)
虽然 tie 通常用于解包 pair 或 tuple,但你也可以通过它来赋值,尤其是在解构赋值中。
int a = 2;
string b = "banana";
tie(a, b) = make_pair(1, "apple"); // a 和 b 现在分别是 1 和 "apple"
使用结构化绑定(C++17 及以上)
C++17 引入了结构化绑定,允许你直接解构 pair 并赋值。
auto [a, b] = make_pair(1, "apple"); // a 是 int 类型,值为 1;b 是 string 类型,值为 "ap
map
#include<bits/stdc++.h>
using namespace std;
int main() {
/*map*/
map<string, int> m;
// 插入元素
m.insert(make_pair("apple", 5));
m["banana"] = 3;
// 访问元素
cout << "apple: " << m["apple"] << endl;
// 检查元素是否存在
if (m.find("cherry") != m.end()) {
cout << "cherry found" << endl;
} else {
cout << "cherry not found" << endl;
}
// 遍历 map
for (const auto& pair : m) {
cout << pair.first << " has " << pair.second << " units" << endl;
}
// 获取 map 的大小
cout << "Size of map: " << m.size() << endl;
return 0;
}
在 C++ 中,map 容器提供了一个成员函数 find,用于在 map 中查找一个键。这个函数接受一个键作为参数,并返回一个迭代器。如果找到了这个键,则返回指向相应元素的迭代器;如果没有找到,则返回一个特殊的迭代器 end,它表示 map 结尾的位置,而不是一个有效的元素位置。因此,表达式 m.find("cherry") != m.end() 用于检查键 "cherry" 是否存在于 map m 中。
m.find("cherry"):调用map的find方法尝试在map中找到键"cherry"。m.end():返回一个迭代器,它表示map的末尾(注意,这不是最后一个元素,而是末尾之后的位置,也就是不存在的“下一个位置”)。!=:比较两个迭代器是否不相等。
如果 find 方法返回的迭代器不等于 end() 迭代器,这意味着 "cherry" 存在于 map 中,因为 find 方法找到了一个有效位置,而不是末尾。如果 find 返回的迭代器等于 end(),则表示 "cherry" 不在 map 中。
set
#include<bits/stdc++.h>
using namespace std;
int main() {
/*set*/
set<int> s;
// 插入元素
s.insert(4);
s.insert(1);
s.insert(2);
// 尝试插入重复元素(不会成功)
s.insert(2);
// 访问和遍历 set
for (int element : s) {
cout << element << " ";
}
cout << endl;
// 检查元素是否存在
if (s.find(3) != s.end()) {
cout << "3 found" << endl;
} else {
cout << "3 not found" << endl;
}
// 获取 set 的大小
cout << "Size of set: " << s.size() << endl;
// 删除元素
s.erase(1);
cout << "After erasing 1: ";
for (int element : s) {
cout << element << " ";
}
cout << endl;
return 0;
}
s.insert(4);
s.insert(1);
s.insert(2);
-
执行以上代码之后,为什么遍历结果是1 2 4 ?
在 C++ 中,
std::set是基于红黑树(一种自平衡二叉查找树)实现的。这意味着它会自动将插入的元素排序。当你向std::set中插入元素时,它会根据元素的值将它们排序(默认情况下是升序)。因此,无论你以什么顺序插入元素,当你遍历这个集合时,元素会按照升序排列。 -
这个自动排序的特性使得
std::set非常适用于需要快速查找、插入和删除操作且元素不重复的情况,同时还需要保持元素有序的场景。