std::map

本文详细介绍了C++标准库中的std::map容器,包括其成员函数如构造、访问、迭代器、容量修改、查找等操作,并通过示例代码展示其用法。std::map是一个有序键值对容器,使用红黑树实现,键是唯一的。文章还涵盖了非成员函数,如比较操作和容器操作。

std::map

介绍

成员函数

非成员函数

介绍

// map 模板定义
template<class Key, class T, class Compare = std::less<Key>, class Allocator = std::allocator<std::pair<const Key, T>>> class map;	
namespace pmr {
    template< class Key, class T, class Compare = std::less<Key> >
    using map = std::map<Key, T, Compare, std::pmr::polymorphic_allocator<std::pair<const Key, T>>>
}
  • std::map 介绍摘选自 cppreference.com 中文网 std::map 介绍
  • std::map 是有序键值对容器,它的元素的键是唯一的
  • 用比较函数 Compare 排序键、搜索、移除和插入操作拥有对数复杂度
  • map 通常实现为红黑树
  • 标准库使用比较 (Compare) 概念时用等价关系确定唯一性
  • 不精确地说,如果两个对象 a 与 b 相互不比较小于对方:!comp(a, b) && !comp(b, a),那么认为它们等价

成员函数

构造析构
#include <QCoreApplication>
#include <algorithm>
#include <iostream>
#include <map>
#include <string>

auto Print(const std::string &msg, const std::map<int, int> &lst) {
  std::cout << msg << " : ";
  for (const auto &pa : lst) {
    std::cout << pa.first << " - " << pa.second << "\t";
  }
  std::cout << "\n";
}

int main(int argc, char *argv[]) {
  QCoreApplication a(argc, argv);

  using map_int = std::map<int, int>;
  map_int m1; //默认构造
  Print("m1", m1);

  std::allocator<std::pair<int, int>> alloc;
  std::less<int> cmp;
  map_int m2(cmp, alloc); //设置比较器和分配器
  Print("m2", m2);

  map_int m3(alloc); //设置分配器
  Print("m3", m3);

  map_int m4{{2, 2}, {3, 3}, {4, 4}};
  Print("m4", m4);
  map_int m5(m4.begin(), m4.end()); //迭代器初始化
  Print("m5", m5);

  map_int m6(m5); //拷贝构造初始化
  Print("m6", m6);

  map_int m7(std::move(m6)); //移动构造初始化
  Print("m7", m7);

  map_int m8{{2, 2}, {3, 3}, {4, 4}}; //初始化列表
  Print("m8", m8);

  //析构函数默认
  return 0; // a.exec();
}

输出结果:
m1 :
m2 :
m3 :
m4 : 2 - 2 3 - 3 4 - 4
m5 : 2 - 2 3 - 3 4 - 4
m6 : 2 - 2 3 - 3 4 - 4
m7 : 2 - 2 3 - 3 4 - 4
m8 : 2 - 2 3 - 3 4 - 4

元素访问
auto Print(const std::string &msg, const std::map<int, int> &lst) {
  std::cout << msg << " : ";
  for (const auto &pa : lst) {
    std::cout << pa.first << " - " << pa.second << "\t";
  }
  std::cout << "\n";
}

int main(int argc, char *argv[]) {
  QCoreApplication a(argc, argv);

  using map_int = std::map<int, int>;
  map_int m1{{100, 10}, {200, 20}, {300, 30}, {400, 40}, {500, 50}};
  Print("m1", m1);

  std::cout << "m1.at(100) : " << m1.at(100) << std::endl;
  std::cout << "m1.at(300) : " << m1.at(300) << std::endl;
  std::cout << "m1.at(500) : " << m1.at(500) << std::endl;

  std::cout << "m1[100] : " << m1[100] << std::endl;
  std::cout << "m1[300] : " << m1[300] << std::endl;
  std::cout << "m1[500] : " << m1[500] << std::endl;

  return 0; // a.exec();
}

输出结果:
m1 : 100 - 10 200 - 20 300 - 30 400 - 40 500 - 50
m1.at(100) : 10
m1.at(300) : 30
m1.at(500) : 50
m1[100] : 10
m1[300] : 30
m1[500] : 50

迭代器
auto Print(const std::string &msg, const std::map<int, int> &lst) {
  std::cout << msg << " : ";
  for (const auto &pa : lst) {
    std::cout << pa.first << " - " << pa.second << "\t";
  }
  std::cout << "\n";
}

int main(int argc, char *argv[]) {
  QCoreApplication a(argc, argv);

  using map_int = std::map<int, int>;
  map_int m1{{100, 10}, {200, 20}, {300, 30}, {400, 40}, {500, 50}};
  Print("m1", m1);

  map_int::iterator iter = m1.begin();
  std::cout << "m1 : ";
  for (; iter != m1.end(); ++iter) {
    std::cout << iter->first << " - " << iter->second << "\t";
  }
  std::cout << "\n";

  map_int::const_iterator citer = m1.begin(); //返回指向起始的迭代器
  std::cout << "m1 : ";
  for (; citer != m1.end(); ++citer) {
    std::cout << citer->first << " - " << citer->second << "\t";
  }
  std::cout << "\n";

  map_int::reverse_iterator rbiter = m1.rbegin(); //返回指向起始的逆向迭代器
  std::cout << "m1 : ";
  for (; rbiter != m1.rend(); ++rbiter) {
    std::cout << rbiter->first << " - " << rbiter->second << "\t";
  }
  std::cout << "\n";

  map_int::const_reverse_iterator crbiter = m1.crbegin(); //返回指向起始的迭代器
  std::cout << "m1 : ";
  for (; crbiter != m1.crend(); ++crbiter) {
    std::cout << crbiter->first << " - " << crbiter->second << "\t";
  }
  std::cout << "\n";

  return 0; // a.exec();
}

输出结果:
m1 : 100 - 10 200 - 20 300 - 30 400 - 40 500 - 50
m1 : 100 - 10 200 - 20 300 - 30 400 - 40 500 - 50
m1 : 100 - 10 200 - 20 300 - 30 400 - 40 500 - 50
m1 : 500 - 50 400 - 40 300 - 30 200 - 20 100 - 10
m1 : 500 - 50 400 - 40 300 - 30 200 - 20 100 - 10

容量
auto Print(const std::string &msg, const std::map<int, int> &lst) {
  std::cout << msg << " : ";
  for (const auto &pa : lst) {
    std::cout << pa.first << " - " << pa.second << "\t";
  }
  std::cout << "\n";
}

int main(int argc, char *argv[]) {
  QCoreApplication a(argc, argv);

  using map_int = std::map<int, int>;
  map_int m1{{100, 10}, {200, 20}, {300, 30}, {400, 40}, {500, 50}};
  Print("m1", m1);

  //检查容器是否为空
  std::cout << std::boolalpha << "m1.empty() : " << m1.empty() << std::endl;

  std::cout << "m1.size() : " << m1.size() << std::endl; //返回容纳的元素数
  std::cout << "m1.max_size() : " << m1.max_size()
            << std::endl; //返回可容纳的最大元素数,和平台有关

  return 0; // a.exec();
}

输出结果:
m1 : 100 - 10 200 - 20 300 - 30 400 - 40 500 - 50
m1.empty() : false
m1.size() : 5
m1.max_size() : 461168601842738790

修改器
auto Print(const std::string &msg, const std::map<int, int> &lst) {
  std::cout << msg << " : ";
  for (const auto &pa : lst) {
    std::cout << pa.first << " - " << pa.second << "\t";
  }
  std::cout << "\n";
}

int main(int argc, char *argv[]) {
  QCoreApplication a(argc, argv);

  using map_int = std::map<int, int>;
  map_int m1{{100, 10}, {200, 20}, {300, 30}, {400, 40}, {500, 50}};
  Print("m1", m1);

  m1.clear(); //  清除内容
  Print("m1", m1);
  m1.insert(std::pair<int, int>(1, 10)); //插入元素或结点
  m1.insert({2, 20});
  Print("m1", m1);
  m1.emplace(3, 30); //原位构造元素
  m1.emplace(4, 40);
  Print("m1", m1);

  m1.emplace_hint(m1.end(), 5, 50); //使用提示原位构造元素
  m1.emplace_hint(m1.end(), 6, 60);
  m1.emplace_hint(m1.end(), 7, 70);
  Print("m1", m1);
  m1.erase(m1.begin());
  Print("m1", m1);
  
  return 0; // a.exec();
}

输出结果:
m1 : 100 - 10 200 - 20 300 - 30 400 - 40 500 - 50
m1 :
m1 : 1 - 10 2 - 20
m1 : 1 - 10 2 - 20 3 - 30 4 - 40
m1 : 1 - 10 2 - 20 3 - 30 4 - 40 5 - 50 6 - 60 7 - 70
m1 : 2 - 20 3 - 30 4 - 40 5 - 50 6 - 60 7 - 70

查找
auto Print(const std::string &msg, const std::map<int, int> &lst) {
  std::cout << msg << " : ";
  for (const auto &pa : lst) {
    std::cout << pa.first << " - " << pa.second << "\t";
  }
  std::cout << "\n";
}

int main(int argc, char *argv[]) {
  QCoreApplication a(argc, argv);

  using map_int = std::map<int, int>;
  map_int m1{{100, 10}, {200, 20}, {300, 30}, {400, 40}, {500, 50}};
  Print("m1", m1);

  std::cout << "m1.count() : " << m1.count(300)
            << std::endl; //返回匹配特定键的元素数量
  auto it = m1.find(200); //寻找带有特定键的元素
  if (it == m1.end()) {
    std::cout << "m1.find(200) : m1.end()" << std::endl;
  } else {
    std::cout << "m1.find(200) : " << it->first << " - " << it->second
              << std::endl;
  }

  //返回容器中所有拥有给定关键的元素范围。范围以二个迭代器定义,一个指向首个不小于
  // key 的元素,另一个指向首个大于 key 的元素。首个迭代器可以换用 lower_bound()
  //获得,而第二迭代器可换用 upper_bound() 获得
  std::pair<map_int::iterator, map_int::iterator> pa =
      m1.equal_range(100); //返回匹配特定键的元素范围

  std::cout << pa.first->first << " - " << pa.first->second << std::endl;
  std::cout << pa.second->first << " - " << pa.second->second << std::endl;

  map_int::iterator lit =
      m1.lower_bound(300); //返回指向首个不小于给定键的元素的迭代器
  std::cout << "m1.lower_bound(300) : " << lit->first << " - " << lit->second
            << std::endl;

  lit = m1.upper_bound(100); //返回指向首个大于给定键的元素的迭代器
  std::cout << "m1.upper_bound(100) : " << lit->first << " - " << lit->second
            << std::endl;
  return 0; // a.exec();
}

输出结果:
m1 : 100 - 10 200 - 20 300 - 30 400 - 40 500 - 50
m1.count() : 1
m1.find(200) : 200 - 20
100 - 10
200 - 20
m1.lower_bound(300) : 300 - 30
m1.upper_bound(100) : 200 - 20

非成员函数

auto Print(const std::string &msg, const std::map<int, int> &lst) {
  std::cout << msg << " : ";
  for (const auto &pa : lst) {
    std::cout << pa.first << " - " << pa.second << "\t";
  }
  std::cout << "\n";
}

int main(int argc, char *argv[]) {
  QCoreApplication a(argc, argv);

  using map_int = std::map<int, int>;
  map_int m1{{100, 10}, {200, 20}, {300, 30}, {400, 40}, {500, 50}};
  map_int m2{{100, 1}, {200, 2}, {300, 3}, {400, 4}, {500, 5}};
  Print("m1", m1);
  Print("m2", m2);

  std::cout.setf(std::ios::boolalpha);
  std::cout << "m1 == m2 : " << (m1 == m2) << std::endl;
  std::cout << "m1 != m2 : " << (m1 != m2) << std::endl;
  std::cout << "m1 > m2 : " << (m1 > m2) << std::endl;
  std::cout << "m1 >= m2 : " << (m1 >= m2) << std::endl;
  std::cout << "m1 < m2 : " << (m1 < m2) << std::endl;
  std::cout << "m1 <= m2 : " << (m1 <= m2) << std::endl;
  std::cout.unsetf(std::ios::boolalpha);
  // c++20 废弃以上操作符重载,提供三路运算符 operator <=> ()

  std::swap(m1, m2);
  Print("m1", m1);
  Print("m2", m2);

  return 0; // a.exec();
}

输出结果:
m1 : 100 - 10 200 - 20 300 - 30 400 - 40 500 - 50
m2 : 100 - 1 200 - 2 300 - 3 400 - 4 500 - 5
m1 == m2 : false
m1 != m2 : true
m1 > m2 : true
m1 >= m2 : true
m1 < m2 : false
m1 <= m2 : false
m1 : 100 - 1 200 - 2 300 - 3 400 - 4 500 - 5
m2 : 100 - 10 200 - 20 300 - 30 400 - 40 500 - 50

起始

### C++ `std::map` 使用方法及示例 #### 1. 简介 `std::map` 是 C++ 标准模板库(STL)中的一个关联容器,用于存储键值对。其内部实现基于红黑树,因此具有自动排序特性,并支持高效的插入、删除和查找操作[^2]。 --- #### 2. 基本用法 ##### 2.1 定义和初始化 可以通过多种方式定义并初始化 `std::map`: ```cpp #include <iostream> #include <map> int main() { // 方式一:默认构造 std::map<int, std::string> map1; // 方式二:通过初始列表构造 std::map<int, std::string> map2 = {{1, "one"}, {2, "two"}}; // 方式三:拷贝构造 std::map<int, std::string> map3(map2); return 0; } ``` --- ##### 2.2 插入元素 可以使用以下几种方法向 `std::map` 中插入数据: ```cpp #include <iostream> #include <map> int main() { std::map<int, std::string> myMap; // 方法一:使用下标运算符 myMap[1] = "apple"; // 方法二:使用 insert 函数 myMap.insert({2, "banana"}); myMap.insert(std::make_pair(3, "cherry")); // 打印结果 for (const auto& pair : myMap) { std::cout << pair.first << ": " << pair.second << std::endl; } return 0; } ``` --- ##### 2.3 查找元素 可通过 `find()` 或下标运算符来访问特定键对应的值: ```cpp #include <iostream> #include <map> int main() { std::map<std::string, int> fruitCount = {{"apple", 3}, {"banana", 5}}; // 使用 find() auto it = fruitCount.find("apple"); if (it != fruitCount.end()) { std::cout << "Found apple with count: " << it->second << std::endl; } // 使用下标运算符 std::cout << "Banana count: " << fruitCount["banana"] << std::endl; return 0; } ``` 注意:如果使用下标运算符访问不存在的键,则会创建该键并将值设为默认值(对于整数类型,默认值为 0)。这可能会导致意外行为[^2]。 --- ##### 2.4 删除元素 可利用 `erase()` 函数删除指定键或范围内的元素: ```cpp #include <iostream> #include <map> int main() { std::map<char, int> charCounts = {{'a', 1}, {'b', 2}, {'c', 3}}; // 删除单个元素 charCounts.erase('b'); // 删除多个元素 charCounts.erase(charCounts.begin(), charCounts.find('c')); for (const auto& pair : charCounts) { std::cout << pair.first << ": " << pair.second << std::endl; } return 0; } ``` --- #### 3. 常用函数详解 ##### 3.1 大小与检查是否为空 - `size()` 返回当前映射中键值对的数量。 - `empty()` 判断映射是否为空。 ```cpp #include <iostream> #include <map> int main() { std::map<int, double> data; std::cout << "Size: " << data.size() << ", Empty: " << std::boolalpha << data.empty() << std::endl; data[1] = 3.14; std::cout << "Size after insertion: " << data.size() << ", Empty: " << data.empty() << std::endl; return 0; } ``` --- ##### 3.2 遍历 `std::map` 可以通过迭代器或者基于范围的循环遍历整个映射: ```cpp #include <iostream> #include <map> int main() { std::map<std::string, int> scores = {{"Alice", 90}, {"Bob", 85}}; // 迭代器遍历 for (auto it = scores.begin(); it != scores.end(); ++it) { std::cout << it->first << ": " << it->second << std::endl; } // 范围基遍历 for (const auto& [key, value] : scores) { std::cout << key << ": " << value << std::endl; } return 0; } ``` --- ##### 3.3 统计键的数量 `count(key)` 可返回给定键是否存在及其数量(通常只为 0 或 1): ```cpp #include <iostream> #include <map> int main() { std::map<int, std::string> names = {{1, "John"}, {2, "Jane"}}; std::cout << "Key 1 exists? " << names.count(1) << std::endl; std::cout << "Key 3 exists? " << names.count(3) << std::endl; return 0; } ``` --- ##### 3.4 获取范围 `lower_bound()` 和 `upper_bound()` 提供了获取某个范围内键值的能力: ```cpp #include <iostream> #include <map> int main() { std::map<int, std::string> numbers = {{1, "One"}, {2, "Two"}, {3, "Three"}}; // lower_bound auto lb = numbers.lower_bound(2); std::cout << "Lower bound of 2 is: " << lb->first << " -> " << lb->second << std::endl; // upper_bound auto ub = numbers.upper_bound(2); std::cout << "Upper bound of 2 is: " << ub->first << " -> " << ub->second << std::endl; return 0; } ``` --- #### 4. 注意事项 - **自动排序**:`std::map` 默认按键升序排列,无法更改此顺序[^2]。 - **性能特点**:由于底层采用平衡二叉搜索树,插入、删除和查找的时间复杂度均为 O(log n)[^2]。 --- #### 5. 应用场景 适合需要按键有序存储且频繁执行查找操作的场合。例如,在统计单词频率时,可以用 `std::map` 存储每个单词及其出现次数[^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值