文章目录
- map (映射)
- 定义
- 注意
- 优点
- map构造和赋值
- 构造
- 赋值
- 示例
- map大小和交换
- 函数原型
- 示例
- map插入和删除
- 函数原型
- 四种插入方式
- 示例
- map查找和统计
- 函数原型
- 示例
- map容器排序
- multimap 容器 (多重映射)
- 定义
- 特点
- 和map的区别
- 示例
map (映射)
定义
C++中的map是一种关联容器,它提供了一种键-值(key-value)对的存储方式。map容器中的元素是按照键的顺序进行排序的,并且每个键都唯一。通过使用键来访问其相应的值,我们可以在O(log n)的时间复杂度内进行快速的查找、插入和删除操作。
map与set类似,但不同之处在于map存储的是键值对(key-value pair),而set只存储单个元素。每个键值对在map中被视为一个元素,由键(key)和值(value)组成。键用于唯一标识元素,值则是与键相关联的数据。
注意
- map中所有元素都是pair
- pair中第一个元素为key(键值),起到索引作用,第二个元素为value(实值)
map
是一个有序容器,所有元素都会根据元素的键值自动排序- 每个键只能在
map
中唯一出现。如果插入一个已存在的键,那么新的值会取代旧的值。
优点
- 快速查找
map基于红黑树实现,这使得在大量数据情况下,查找操作具有较好的时间复杂度(平均为O(log n))。因此,可以根据key值快速找到value值 - 有序性
map以键的顺序进行排序,这意味着通过map迭代器遍历时可以按照键的有序性进行操作。这对于需要按照键的顺序访问数据的场景非常方便。 - 唯一键
map中每个键都是唯一的,这意味着相同的键只会出现一次。当需要确保数据中的键是唯一的时,map提供了一种有效的数据结构来实现这一点。 - 稳定性
由于map基于红黑树实现,它对插入和删除操作的平均时间复杂度为O(log n),这使得在频繁更新数据的场景中也能保持较好的性能稳定性。
map构造和赋值
构造
map<T1, T2> mp;
//map默认构造函数:map(const map &mp);
//拷贝构造函数
赋值
map& operator=(const map &mp);
//重载等号操作符
示例
注意:map中所有元素都是成对出现,插入数据时候要使用对组
#include <iostream>
#include <map>int main() {// 创建一个空的mapstd::map<int, std::string> mp;// 使用insert插入元素mp.insert(std::make_pair(1, "apple"));mp.insert(std::make_pair(2, "banana"));mp.insert(std::make_pair(3, "orange"));// 输出map的元素for (const auto& pair : mp) {std::cout << pair.first << ": " << pair.second << std::endl;}// 使用拷贝构造函数创建一个新的mapstd::map<int, std::string> copyMap(mp);// 使用等号操作符进行赋值std::map<int, std::string> assignedMap;assignedMap = mp;return 0;
}
输出
1: apple
2: banana
3: orange
map大小和交换
函数原型
size();
//返回容器中元素的数目empty();
//判断容器是否为空swap(st);
//交换两个集合容器
示例
#include <iostream>
#include <map>int main() {// 创建一个mapstd::map<int, std::string> mp;// 插入一些元素mp.insert(std::make_pair(1, "apple"));mp.insert(std::make_pair(2, "banana"));mp.insert(std::make_pair(3, "orange"));// 获取容器中元素的数目std::cout << "Size: " << mp.size() << std::endl;// 判断容器是否为空if (mp.empty()) {std::cout << "Map is empty" << std::endl;} else {std::cout << "Map is not empty" << std::endl;}// 创建另一个mapstd::map<int, std::string> anotherMap;anotherMap.insert(std::make_pair(4, "grape"));anotherMap.insert(std::make_pair(5, "kiwi"));// 交换两个mapmp.swap(anotherMap);// 输出交换后的结果std::cout << "Map after swap:" << std::endl;for (const auto& pair : mp) {std::cout << pair.first << ": " << pair.second << std::endl;}return 0;
}
输出结果
Size: 3
Map is not empty
Map after swap:
4: grape
5: kiwi
分析
在上述示例中,我们首先创建了一个map<int, string>,并插入了几个键值对。然后我们使用size()函数获取容器中元素的数目,并使用empty()函数判断容器是否为空。
接下来,我们创建了另一个map anotherMap,并插入了一些元素。然后使用swap()函数交换了两个map的内容,将原来的mp与anotherMap进行了交换。最后,我们遍历并输出了交换后的map的元素。
需要注意的是,swap()函数会直接交换两个map的内容,而不是创建副本或者复制元素。
map插入和删除
函数原型
insert(elem);
//在容器中插入元素。clear();
//清除所有元素erase(pos);
//删除pos迭代器所指的元素,返回下一个元素的迭代器。erase(beg, end);
//删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。erase(key);
//删除容器中值为key的元素。
四种插入方式
-
m.insert(pair<int, int>(1, 10));
-
m.insert(make_pair(2, 20));
-
m.insert(map<int, int>::value_type(3, 30));
-
m[4] = 40;
注意
map<int, int>::value_type(3, 30)
是一个创建 map
中键值对的方法。它使用了 map
的嵌套类型 value_type
,表示键值对的类型。注意,map<int, int>::value_type
是 pair<const Key, T>
的别名,其中 Key
是键的类型,T
是值的类型。
value_type 是 map 类的内部类型,表示键值对的类型。在这里,map<int, int>::value_type 表示 pair<const int, int>,即键为 const int 类型,值为 int 类型的键值对。
这种方式仅适用于 C++03 标准及之前的版本。从 C++11 标准开始,我们可以直接使用简化的插入语法,如 m.insert({3, 30})
示例
#include <iostream>
#include <map>
void printMap(map<int,int>&m)
{for (map<int, int>::iterator it = m.begin(); it != m.end(); it++){cout << "key = " << it->first << " value = " << it->second << endl;}cout << endl;
}int main() {//插入map<int, int> m;//第一种插入方式m.insert(pair<int, int>(1, 10));//第二种插入方式m.insert(make_pair(2, 20));//第三种插入方式m.insert(map<int, int>::value_type(3, 30));//第四种插入方式m[4] = 40; printMap(m);//删除m.erase(m.begin());printMap(m);m.erase(3);printMap(m);//清空m.erase(m.begin(),m.end());m.clear();printMap(m);return 0;
}
在上述示例中,我们首先创建了一个map<int, int>,然后使用四种不同的插入方式向map中插入了一些元素,并使用printMap函数输出map的内容。
接下来,我们使用erase函数删除了第一个元素和键为3的元素,并再次使用printMap函数输出了更新后的map。
最后,我们使用clear函数清空了整个map,并再次使用printMap函数输出了清空后的map。
需要注意的是,map中的元素是按照键的顺序进行排序的,而且键必须是唯一的。同时,使用erase函数删除元素时可以指定要删除的元素的位置或者键值。
map查找和统计
函数原型
find(key);
//查找key是否存在,若存在,返回该键的元素的迭代器;否则返回set.end();count(key);
//统计key的元素个数 (对于map,结果为0或者1, 最多一个不重复)
示例
#include <iostream>
#include <map>int main() {std::map<int, int> m;// 插入元素m.insert(std::pair<int, int>(1, 10));m.insert(std::pair<int, int>(2, 20));m.insert(std::pair<int, int>(3, 30));m.insert(std::pair<int, int>(4, 40));// 使用 find 函数查找键为 3 的元素std::map<int, int>::iterator it = m.find(3);if (it != m.end()) {std::cout << "键为 3 的元素存在,值为 " << it->second << std::endl;} else {std::cout << "键为 3 的元素不存在" << std::endl;}// 使用 count 函数统计键为 4 的元素个数int count = m.count(4);std::cout << "键为 4 的元素个数为 " << count << std::endl;// 查找一个不存在的键it = m.find(5);if (it != m.end()) {std::cout << "键为 5 的元素存在,值为 " << it->second << std::endl;} else {std::cout << "键为 5 的元素不存在" << std::endl;}return 0;
}
输出
键为 3 的元素存在,值为 30
键为 4 的元素个数为 1
键为 5 的元素不存在
在上述示例中,我们首先创建了一个map<int, int>并向其中插入了几个元素。然后,我们使用find(key)函数来查找键为 3 的元素,并根据返回的迭代器判断该元素是否存在。
接下来,我们使用count(key)函数统计键为 4 的元素的个数。
最后,我们使用find(key)函数查找一个不存在的键 5,并根据返回的迭代器判断该元素是否存在。
需要注意的是,对于count(key)函数来说,由于map容器的特性,它的返回值要么是 0(表示键不存在),要么是 1(表示键存在)。因为map 中每个键都是唯一的。
map容器排序
- map容器默认排序规则为 按照key值进行 从小到大排序
- 利用仿函数可以指定map容器的排序规则
- 对于自定义数据类型,map必须要指定排序规则,同set容器
重载 operator()
运算符是定义一个仿函数的必要条件。实际上,仿函数就是一个类对象,在使用仿函数时,我们可以像调用函数一样使用它进行计算。在 C++ 中,仿函数可以重载多个运算符,但重载 operator()
运算符是最常见的情况,因为它使得对象可以被像函数一样调用,并且提供了比较接近函数调用的语法。除了重载 operator()
运算符外,仿函数还可以根据需要重载其他运算符,例如 operator+
、operator-
等运算符,以实现特定的功能。
示例:
#include <iostream>
#include <map>// 自定义仿函数类来指定排序规则
struct MyComparator {bool operator()(int a, int b) const {return a > b; // 从大到小排序}
};int main() {std::map<int, std::string, MyComparator> m; // 使用自定义排序规则的 map// 向 map 中插入元素m.insert(std::pair<int, std::string>(3, "Alice"));m.insert(std::pair<int, std::string>(1, "Bob"));m.insert(std::pair<int, std::string>(4, "Charlie"));m.insert(std::pair<int, std::string>(2, "David"));// 打印按照自定义排序规则排序后的结果for (const auto& pair : m) {std::cout << pair.first << ": " << pair.second << std::endl;}return 0;
}
输出
4: Charlie
3: Alice
2: David
1: Bob
在上述示例中,我们定义了一个名为 MyComparator 的仿函数类,用于指定排序规则。该仿函数类重载了 operator() 运算符,其中通过返回 a > b 来实现从大到小排序。
然后,我们创建了一个类型为 map<int, string> 的 map 容器,并将自定义的 MyComparator 类作为第三个模板参数传递给 map,以指定排序规则为从大到小。
接下来,我们向 map 中插入了几个元素,并通过遍历 map 打印出按照自定义排序规则排序后的结果。
需要注意的是,在使用自定义排序规则时,关键是要将该规则作为 map 的第三个模板参数进行指定,以告诉 map 使用自定义排序规则。
multimap 容器 (多重映射)
定义
multimap 是 C++ STL 中的一个关联容器,它提供了一种键值对的存储方式,允许一个键对应多个值。multimap 容器中的元素按照键的自然顺序进行排序,并且可以有重复的键。
特点
可以有重复的键。
键和值可以是任意数据类型。
键值对是按照键的自然顺序进行排序的。
提供了高效的插入、查找和删除操作
和map的区别
multimap 可以有多个相同的键,map不行,其他二者几乎一致
示例
#include <iostream>
#include <map>int main() {std::multimap<int, std::string> mm;// 插入键值对mm.insert(std::pair<int, std::string>(3, "Alice"));mm.insert(std::pair<int, std::string>(1, "Bob"));mm.insert(std::pair<int, std::string>(2, "Charlie"));mm.insert(std::pair<int, std::string>(3, "David"));// 遍历 multimapfor (const auto& pair : mm) {std::cout << pair.first << ": " << pair.second << std::endl;}return 0;
}
输出
1: Bob
2: Charlie
3: Alice
3: David
在上述示例中,我们创建了一个 multimap<int, string> 类型的 multimap 容器,并向其中插入了几个键值对。其中,键是 int 类型,值是 string 类型。
然后,我们通过遍历 multimap 容器,打印出所有的键值对。
需要注意的是,由于 multimap 容器允许有重复的键,因此在遍历时,可能会输出相同键的多个值。