Day 28 C++ (映射)map 容器 / multimap 容器 (多重映射)

文章目录

  • 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 mp; //map默认构造函数:
  • map(const map &mp); //拷贝构造函数
赋值
  • map& operator=(const map &mp); //重载等号操作符
示例

注意:map中所有元素都是成对出现,插入数据时候要使用对组

#include 
#include 

int main() {
    // 创建一个空的map
    std::map 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;
    }

    // 使用拷贝构造函数创建一个新的map
    std::map copyMap(mp);

    // 使用等号操作符进行赋值
    std::map assignedMap;
    assignedMap = mp;

    return 0;
}

输出
1: apple
2: banana
3: orange


map大小和交换

函数原型
  • size(); //返回容器中元素的数目
  • empty(); //判断容器是否为空
  • swap(st); //交换两个集合容器
示例
#include 
#include 

int main() {
    // 创建一个map
    std::map 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;
    }

    // 创建另一个map
    std::map anotherMap;
    anotherMap.insert(std::make_pair(4, "grape"));
    anotherMap.insert(std::make_pair(5, "kiwi"));

    // 交换两个map
    mp.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,并插入了几个键值对。然后我们使用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(1, 10));

  • m.insert(make_pair(2, 20));

  • m.insert(map::value_type(3, 30));

  • m[4] = 40;

注意

map::value_type(3, 30) 是一个创建 map 中键值对的方法。它使用了 map 的嵌套类型 value_type,表示键值对的类型。注意,map::value_typepair 的别名,其中 Key 是键的类型,T 是值的类型。

value_type 是 map 类的内部类型,表示键值对的类型。在这里,map::value_type 表示 pair,即键为 const int 类型,值为 int 类型的键值对。

这种方式仅适用于 C++03 标准及之前的版本。从 C++11 标准开始,我们可以直接使用简化的插入语法,如 m.insert({3, 30})

示例
#include 
#include 
void printMap(map&m)
{
	for (map::iterator it = m.begin(); it != m.end(); it++)
	{
		cout << "key = " << it->first << " value = " << it->second << endl;
	}
	cout << endl;
}

int main() {
	//插入
	map m;
	//第一种插入方式
	m.insert(pair(1, 10));
	//第二种插入方式
	m.insert(make_pair(2, 20));
	//第三种插入方式
	m.insert(map::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,然后使用四种不同的插入方式向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 
#include 

int main() {
    std::map m;
    
    // 插入元素
    m.insert(std::pair(1, 10));
    m.insert(std::pair(2, 20));
    m.insert(std::pair(3, 30));
    m.insert(std::pair(4, 40));

    // 使用 find 函数查找键为 3 的元素
    std::map::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并向其中插入了几个元素。然后,我们使用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 
#include 

// 自定义仿函数类来指定排序规则
struct MyComparator {
    bool operator()(int a, int b) const {
        return a > b; // 从大到小排序
    }
};

int main() {
    std::map m; // 使用自定义排序规则的 map

    // 向 map 中插入元素
    m.insert(std::pair(3, "Alice"));
    m.insert(std::pair(1, "Bob"));
    m.insert(std::pair(4, "Charlie"));
    m.insert(std::pair(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 的 map 容器,并将自定义的 MyComparator 类作为第三个模板参数传递给 map,以指定排序规则为从大到小。

接下来,我们向 map 中插入了几个元素,并通过遍历 map 打印出按照自定义排序规则排序后的结果。

需要注意的是,在使用自定义排序规则时,关键是要将该规则作为 map 的第三个模板参数进行指定,以告诉 map 使用自定义排序规则。

multimap 容器 (多重映射)

定义

multimap 是 C++ STL 中的一个关联容器,它提供了一种键值对的存储方式,允许一个键对应多个值。multimap 容器中的元素按照键的自然顺序进行排序,并且可以有重复的键。

特点

可以有重复的键。
键和值可以是任意数据类型。
键值对是按照键的自然顺序进行排序的。
提供了高效的插入、查找和删除操作

和map的区别

multimap 可以有多个相同的键,map不行,其他二者几乎一致

示例

#include 
#include 

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"));

    // 遍历 multimap
    for (const auto& pair : mm) {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }

    return 0;
}

输出
1: Bob
2: Charlie
3: Alice
3: David

在上述示例中,我们创建了一个 multimap 类型的 multimap 容器,并向其中插入了几个键值对。其中,键是 int 类型,值是 string 类型。

然后,我们通过遍历 multimap 容器,打印出所有的键值对。

需要注意的是,由于 multimap 容器允许有重复的键,因此在遍历时,可能会输出相同键的多个值。

在这里插入图片描述

你可能感兴趣的:(C,++,c++,开发语言)