您好,登录后才能下订单哦!
在C++编程中,map
和set
是两种非常常用的关联容器。它们基于红黑树(一种自平衡二叉查找树)实现,提供了高效的查找、插入和删除操作。map
和set
的主要区别在于它们存储的元素类型:map
存储键值对(key-value pairs),而set
只存储键(key)。本文将详细介绍map
和set
的使用方法,并通过示例代码帮助读者更好地理解它们的应用场景。
map
的使用map
的基本概念map
是C++标准模板库(STL)中的一种关联容器,它存储的元素是键值对(key-value pairs)。map
中的键是唯一的,每个键对应一个值。map
内部通过红黑树实现,因此它的查找、插入和删除操作的时间复杂度都是O(log n)。
map
的声明和初始化在使用map
之前,需要包含头文件<map>
。map
的声明格式如下:
#include <map>
std::map<KeyType, ValueType> myMap;
其中,KeyType
是键的类型,ValueType
是值的类型。例如,声明一个键为int
、值为std::string
的map
:
std::map<int, std::string> myMap;
map
可以通过以下几种方式进行初始化:
map
。{}
初始化map
。map
进行初始化。示例代码:
#include <iostream>
#include <map>
int main() {
// 默认初始化
std::map<int, std::string> map1;
// 列表初始化
std::map<int, std::string> map2 = {
{1, "apple"},
{2, "banana"},
{3, "cherry"}
};
// 拷贝初始化
std::map<int, std::string> map3(map2);
// 输出map2的内容
for (const auto& pair : map2) {
std::cout << pair.first << ": " << pair.second << std::endl;
}
return 0;
}
map
的常用操作map
提供了多种插入元素的方法,常用的有insert
和emplace
。
insert
:插入一个键值对,如果键已经存在,则插入失败。emplace
:直接构造并插入一个键值对,避免了不必要的拷贝或移动操作。示例代码:
#include <iostream>
#include <map>
int main() {
std::map<int, std::string> myMap;
// 使用insert插入元素
myMap.insert(std::make_pair(1, "apple"));
myMap.insert(std::make_pair(2, "banana"));
// 使用emplace插入元素
myMap.emplace(3, "cherry");
// 输出map的内容
for (const auto& pair : myMap) {
std::cout << pair.first << ": " << pair.second << std::endl;
}
return 0;
}
map
提供了多种访问元素的方法,常用的有operator[]
和at
。
operator[]
:通过键访问值,如果键不存在,则会插入一个默认值。at
:通过键访问值,如果键不存在,则会抛出std::out_of_range
异常。示例代码:
#include <iostream>
#include <map>
int main() {
std::map<int, std::string> myMap = {
{1, "apple"},
{2, "banana"},
{3, "cherry"}
};
// 使用operator[]访问元素
std::cout << "map[1] = " << myMap[1] << std::endl;
// 使用at访问元素
std::cout << "map.at(2) = " << myMap.at(2) << std::endl;
// 访问不存在的键
// std::cout << "map.at(4) = " << myMap.at(4) << std::endl; // 抛出异常
return 0;
}
map
提供了erase
方法来删除元素。erase
可以接受一个键、一个迭代器或一个迭代器范围作为参数。
示例代码:
#include <iostream>
#include <map>
int main() {
std::map<int, std::string> myMap = {
{1, "apple"},
{2, "banana"},
{3, "cherry"}
};
// 删除键为2的元素
myMap.erase(2);
// 删除第一个元素
myMap.erase(myMap.begin());
// 输出map的内容
for (const auto& pair : myMap) {
std::cout << pair.first << ": " << pair.second << std::endl;
}
return 0;
}
map
提供了find
方法来查找元素。find
方法返回一个迭代器,指向找到的元素;如果未找到,则返回end()
。
示例代码:
#include <iostream>
#include <map>
int main() {
std::map<int, std::string> myMap = {
{1, "apple"},
{2, "banana"},
{3, "cherry"}
};
// 查找键为2的元素
auto it = myMap.find(2);
if (it != myMap.end()) {
std::cout << "Found: " << it->first << ": " << it->second << std::endl;
} else {
std::cout << "Not found" << std::endl;
}
// 查找键为4的元素
it = myMap.find(4);
if (it != myMap.end()) {
std::cout << "Found: " << it->first << ": " << it->second << std::endl;
} else {
std::cout << "Not found" << std::endl;
}
return 0;
}
map
map
可以通过迭代器进行遍历。map
的迭代器指向的元素是一个std::pair
,其中first
是键,second
是值。
示例代码:
#include <iostream>
#include <map>
int main() {
std::map<int, std::string> myMap = {
{1, "apple"},
{2, "banana"},
{3, "cherry"}
};
// 使用迭代器遍历map
for (auto it = myMap.begin(); it != myMap.end(); ++it) {
std::cout << it->first << ": " << it->second << std::endl;
}
// 使用范围for循环遍历map
for (const auto& pair : myMap) {
std::cout << pair.first << ": " << pair.second << std::endl;
}
return 0;
}
map
的高级用法map
默认使用std::less
作为比较函数,即按键的升序排列。如果需要自定义比较函数,可以在声明map
时指定。
示例代码:
#include <iostream>
#include <map>
// 自定义比较函数
struct Compare {
bool operator()(const int& a, const int& b) const {
return a > b; // 按降序排列
}
};
int main() {
std::map<int, std::string, Compare> myMap = {
{1, "apple"},
{2, "banana"},
{3, "cherry"}
};
// 输出map的内容
for (const auto& pair : myMap) {
std::cout << pair.first << ": " << pair.second << std::endl;
}
return 0;
}
multimap
multimap
是map
的一个变种,它允许键重复。multimap
的使用方法与map
类似,但由于键可以重复,因此在插入和查找时需要注意。
示例代码:
#include <iostream>
#include <map>
int main() {
std::multimap<int, std::string> myMultimap;
// 插入元素
myMultimap.insert(std::make_pair(1, "apple"));
myMultimap.insert(std::make_pair(2, "banana"));
myMultimap.insert(std::make_pair(1, "apricot"));
// 输出multimap的内容
for (const auto& pair : myMultimap) {
std::cout << pair.first << ": " << pair.second << std::endl;
}
return 0;
}
set
的使用set
的基本概念set
是C++标准模板库(STL)中的一种关联容器,它存储的元素是唯一的键(key)。set
内部通过红黑树实现,因此它的查找、插入和删除操作的时间复杂度都是O(log n)。
set
的声明和初始化在使用set
之前,需要包含头文件<set>
。set
的声明格式如下:
#include <set>
std::set<KeyType> mySet;
其中,KeyType
是键的类型。例如,声明一个键为int
的set
:
std::set<int> mySet;
set
可以通过以下几种方式进行初始化:
set
。{}
初始化set
。set
进行初始化。示例代码:
#include <iostream>
#include <set>
int main() {
// 默认初始化
std::set<int> set1;
// 列表初始化
std::set<int> set2 = {1, 2, 3, 4, 5};
// 拷贝初始化
std::set<int> set3(set2);
// 输出set2的内容
for (const auto& elem : set2) {
std::cout << elem << " ";
}
std::cout << std::endl;
return 0;
}
set
的常用操作set
提供了insert
方法来插入元素。insert
方法返回一个std::pair
,其中first
是一个迭代器,指向插入的元素;second
是一个布尔值,表示插入是否成功。
示例代码:
#include <iostream>
#include <set>
int main() {
std::set<int> mySet;
// 插入元素
mySet.insert(1);
mySet.insert(2);
mySet.insert(3);
// 输出set的内容
for (const auto& elem : mySet) {
std::cout << elem << " ";
}
std::cout << std::endl;
return 0;
}
set
提供了erase
方法来删除元素。erase
可以接受一个键、一个迭代器或一个迭代器范围作为参数。
示例代码:
#include <iostream>
#include <set>
int main() {
std::set<int> mySet = {1, 2, 3, 4, 5};
// 删除键为3的元素
mySet.erase(3);
// 删除第一个元素
mySet.erase(mySet.begin());
// 输出set的内容
for (const auto& elem : mySet) {
std::cout << elem << " ";
}
std::cout << std::endl;
return 0;
}
set
提供了find
方法来查找元素。find
方法返回一个迭代器,指向找到的元素;如果未找到,则返回end()
。
示例代码:
#include <iostream>
#include <set>
int main() {
std::set<int> mySet = {1, 2, 3, 4, 5};
// 查找键为3的元素
auto it = mySet.find(3);
if (it != mySet.end()) {
std::cout << "Found: " << *it << std::endl;
} else {
std::cout << "Not found" << std::endl;
}
// 查找键为6的元素
it = mySet.find(6);
if (it != mySet.end()) {
std::cout << "Found: " << *it << std::endl;
} else {
std::cout << "Not found" << std::endl;
}
return 0;
}
set
set
可以通过迭代器进行遍历。set
的迭代器指向的元素是键本身。
示例代码:
#include <iostream>
#include <set>
int main() {
std::set<int> mySet = {1, 2, 3, 4, 5};
// 使用迭代器遍历set
for (auto it = mySet.begin(); it != mySet.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
// 使用范围for循环遍历set
for (const auto& elem : mySet) {
std::cout << elem << " ";
}
std::cout << std::endl;
return 0;
}
set
的高级用法set
默认使用std::less
作为比较函数,即按键的升序排列。如果需要自定义比较函数,可以在声明set
时指定。
示例代码:
#include <iostream>
#include <set>
// 自定义比较函数
struct Compare {
bool operator()(const int& a, const int& b) const {
return a > b; // 按降序排列
}
};
int main() {
std::set<int, Compare> mySet = {1, 2, 3, 4, 5};
// 输出set的内容
for (const auto& elem : mySet) {
std::cout << elem << " ";
}
std::cout << std::endl;
return 0;
}
multiset
multiset
是set
的一个变种,它允许键重复。multiset
的使用方法与set
类似,但由于键可以重复,因此在插入和查找时需要注意。
示例代码:
#include <iostream>
#include <set>
int main() {
std::multiset<int> myMultiset;
// 插入元素
myMultiset.insert(1);
myMultiset.insert(2);
myMultiset.insert(1);
// 输出multiset的内容
for (const auto& elem : myMultiset) {
std::cout << elem << " ";
}
std::cout << std::endl;
return 0;
}
map
和set
的性能分析map
和set
基于红黑树实现,因此它们的查找、插入和删除操作的时间复杂度都是O(log n)。这使得它们在处理大量数据时仍然能够保持较高的性能。然而,由于红黑树的实现较为复杂,map
和set
的内存开销相对较大。
map
和set
的查找性能非常高效,时间复杂度为O(log n)。这使得它们非常适合用于需要频繁查找的场景。
map
和set
的插入和删除操作的时间复杂度也是O(log n)。由于红黑树的自平衡特性,插入和删除操作不会导致树的高度显著增加,从而保证了操作的稳定性。
map
和set
的内存开销相对较大,因为它们需要存储额外的指针来维护树的结构。此外,map
还需要存储键值对,而set
只需要存储键。
map
和set
的应用场景map
的应用场景map
非常适合用于需要存储键值对并进行快速查找的场景。例如:
set
的应用场景set
非常适合用于需要存储唯一元素并进行快速查找的场景。例如:
map
和set
是C++中非常强大的关联容器,它们基于红黑树实现,提供了高效的查找、插入和删除操作。map
适用于存储键值对,而set
适用于存储唯一元素。通过本文的介绍,读者应该能够掌握map
和set
的基本使用方法,并能够在实际编程中灵活运用它们。
在实际应用中,选择map
还是set
取决于具体的需求。如果需要存储键值对并进行快速查找,map
是更好的选择;如果只需要存储唯一元素并进行快速查找,set
则更为合适。无论选择哪种容器,理解其内部实现和性能特点都是非常重要的,这有助于编写出高效、稳定的代码。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。