【045】C++中map和multimap容器全面解析:深入学习,轻松掌握

这篇具有很好参考价值的文章主要介绍了【045】C++中map和multimap容器全面解析:深入学习,轻松掌握。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、介绍

在C++中,map和multimap容器是非常重要的数据结构,它们提供了一种键值对的映射关系,可以高效地组织和访问数据。map容器中的每个元素都包含一个键和一个值,而multimap容器允许键重复。

这两种容器在实际项目中广泛应用,特别适合需要快速查找和插入元素的场景。其底层实现采用了红黑树等高效的数据结构,map和multimap容器在处理大量数据时具有良好的性能表现。它们也提供了丰富的操作方法和函数,可以轻松地对容器中的数据进行插入、删除、查找和遍历操作。

深入理解map和multimap容器的使用方法和性能特点可以设计高效的数据结构和算法,提高程序的性能和可维护性。

二、map和multimap容器的基本概念

map的特性是,所有元素都会根据元素的键值自动排序。map所有的元素都是pair,同时拥有实值和键值,pair的第一元素被视为键值,第二元素被视为实值,map 不允许两个元素有相同的键值。我们可以通过map的迭代器改变map的键值吗?答案是不行,因为 map的键值关系到 map元素的排列规则,任意改变map键值将会严重破坏map数据组织。如果想要修改元素的实值,那么是可以的。

map和list拥有相同的某些性质,当对它的容器元素进行新增操作或者删除操作时,操作之前的所有迭代器,在操作完成之后依然有效,当然被删除的那个元素的迭代器必然是个例外。

map容器提供了快速的查找、插入和删除操作,时间复杂度为O(log n)。

multimap与map类似,也是键-值对的容器,不同之处在于它允许重复的键。multimap容器同样是有序的,使用红黑树来组织数据,提供了快速的查找、插入和删除操作,时间复杂度为O(log n)。

【045】C++中map和multimap容器全面解析:深入学习,轻松掌握,C++从零开始到精通,c++,学习,开发语言,linux,服务器,C++11,map
map容器:每个元素都是键值-实值成对存储,自动根据键值排序,键值不能重复,不能修改。
multimap和map的操作类似,唯一区别 multimap键值可重复。map和multimap都是以红黑树为底层实现机制

三、map和multimap容器的基本操作

3.1、常用的接口函数API

(1)构造函数:

// 默认构造
map<Key, T> m;		//默认构造一个空的map,键的类型为Key,值的类型为T。
multimap<Key, T> mm;//默认构造一个空的multimap,键的类型为Key,值的类型为T。

// 带有比较函数参数的构造函数:
map< Key, T, Compare> m (const Compare& comp);		//通过指定比较函数comp来构造map。
multimap< Key, T, Compare> mm (const Compare& comp);//通过指定比较函数comp来构造multimap。

// 区间构造函数:
map< Key, T> m (InputIterator first, InputIterator last);		//使用迭代器范围[first, last)内的元素来构造map。
multimap< Key, T> mm (InputIterator first, InputIterator last)	//使用迭代器范围[first, last)内的元素来构造multimap。

//拷贝构造函数:
map< Key, T> m (const map& x);				//拷贝构造一个map,其元素和x相同。
multimap< Key, T> mm (const multimap& x);	//拷贝构造一个multimap,其元素和x相同。

//移动构造函数(C++11引入):
map< Key, T> m (map&& x);			//移动构造一个map,取得x的资源但留下x为空。
multimap< Key, T> mm (multimap&& x);//移动构造一个multimap,取得x的资源但留下x为空。

(2)赋值操作:

// 赋值运算符:
map& operator=(const map& x);			//赋值运算符重载,用x的内容替换当前map的内容。
multimap& operator=(const multimap& x);	//赋值运算符重载,用x的内容替换当前multimap的内容。
// swap函数:
void swap(map& x);		//交换当前map和map x的内容。
void swap(multimap& x);	//交换当前multimap和multimap x的内容。

(3)大小操作:

// size函数:
size_type size() const;	//返回map或multimap中元素的个数。
// empty函数:
bool empty() const;		//如果map或multimap为空,则返回true,否则返回false。

(4)插入数据元素操作:

// insert函数:
pair<iterator, bool> insert(const value_type& val);			//在map中插入val,返回一个pair,第一个元素是一个迭代器,指向新插入的元素或者已存在的相同键的元素,第二个元素是一个bool值,表示插入是否成功。
iterator insert(iterator position, const value_type& val);	//在position位置插入val,并返回插入元素的迭代器。

// emplace函数:使用传入的参数构造元素并插入map中,返回一个pair,
// 第一个元素是一个迭代器,指向新插入的元素或者已存在的相同键的元素,第二个元素是一个bool值,表示插入是否成功。
template <class... Args> pair<iterator, bool> emplace(Args&&... args);

// insert_or_assign函数(C++17及以上版本):如果k存在,则将其关联的值替换为obj,如果不存在则创建一个新的键值对,并返回一个pair,
// 第一个元素是一个迭代器,指向新插入或修改的元素,第二个元素是一个bool值,表示是插入还是修改操作。
- template <class M> pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj);

(5)删除操作:

// erase函数:
iterator erase(iterator position);				//删除指向位置position的元素,并返回指向被删元素之后的下一个元素的迭代器。
size_type erase(const key_type& k);				//删除所有键为k的元素,并返回被删除的元素的数量。
iterator erase(iterator first, iterator last);	//删除[first, last)范围内的所有元素,并返回指向被删元素之后的下一个元素的迭代器。

// clear函数:删除map或multimap中的所有元素。
void clear();

(6)查找操作:

// find函数:
iterator find(const key_type& k);				//查找键为k的元素,并返回指向该元素的迭代器,如果未找到则返回指向尾部的迭代器。
const_iterator find(const key_type& k) const;	//在const map或multimap中查找键为k的元素,并返回指向该元素的const迭代器。

// count函数:返回map或multimap中键等于k的元素的个数。
size_type count(const key_type& k) const;

// lower_bound函数:返回一个迭代器,指向第一个不小于k的元素。
iterator lower_bound(const key_type& k);

// upper_bound函数:返回一个迭代器,指向第一个大于k的元素。
iterator upper_bound(const key_type& k);

// equal_range函数:返回一个pair,包含两个迭代器,第一个迭代器指向键值等于k的第一个元素,第二个迭代器指向键值大于k的第一个元素。
pair<iterator, iterator> equal_range(const key_type& k);

(7)访问元素:

  • operator[]:通过键访问对应的值。
  • at(key):通过键访问对应的值,如果不存在会抛出out_of_range异常。
  • find(key):查找键为key的元素,返回指向该元素的迭代器。

3.2、使用示例

(1)创建和初始化map和multimap容器:

#include <iostream>
#include <map>
#include <unordered_map>

int main() {
    // 创建并初始化map容器
    std::map<int, std::string> myMap = {
        {1, "One"},
        {2, "Two"},
        {3, "Three"}
    };

    // 创建并初始化multimap容器
    std::multimap<int, std::string> myMultimap = {
        {1, "Apple"},
        {2, "Banana"},
        {2, "Orange"}
    };

    // 输出map容器内容
    for (const auto& pair : myMap) {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }

    // 输出multimap容器内容
    for (const auto& pair : myMultimap) {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }

    return 0;
}

(2)插入和删除元素:

#include <iostream>
#include <map>
#include <unordered_map>

int main() {
    // 创建并初始化map容器
    std::map<int, std::string> myMap = {
        {1, "One"},
        {2, "Two"},
        {3, "Three"}
    };

    // 插入元素到map中
    myMap.insert(std::make_pair(4, "Four"));
    myMap[5] = "Five";  // 或者使用下标操作符[]

    // 输出map容器内容
    std::cout << "Map after insertions:" << std::endl;
    for (const auto& pair : myMap) {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }

    // 删除元素从map中
    myMap.erase(2);  // 删除键为2的元素

    // 输出map容器内容
    std::cout << "\nMap after deletion:" << std::endl;
    for (const auto& pair : myMap) {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }

    // 创建并初始化multimap容器
    std::multimap<int, std::string> myMultimap = {
        {1, "Apple"},
        {2, "Banana"},
        {2, "Orange"}
    };

    // 插入元素到multimap中
    myMultimap.insert(std::make_pair(3, "Peach"));

    // 输出multimap容器内容
    std::cout << "\nMultimap after insertions:" << std::endl;
    for (const auto& pair : myMultimap) {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }

    // 删除元素从multimap中
    // 删除multimap中所有键为2的元素
    auto it = myMultimap.find(2);
    myMultimap.erase(it, myMultimap.end());

    // 输出multimap容器内容
    std::cout << "\nMultimap after deletion:" << std::endl;
    for (const auto& pair : myMultimap) {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }

    return 0;
}

(3)查找和访问元素:

#include <iostream>
#include <map>
#include <unordered_map>

int main() {
    // 创建并初始化map容器
    std::map<int, std::string> myMap = {
        {1, "One"},
        {2, "Two"},
        {3, "Three"}
    };

    // 查找和访问map中的元素
    // 使用find函数查找键为2的元素
    auto it = myMap.find(2);
    if (it != myMap.end()) {
        std::cout << "Element with key 2 found: " << it->second << std::endl;
    } else {
        std::cout << "Element with key 2 not found" << std::endl;
    }

    // 修改元素的值
    myMap[1] = "One (updated)";

    // 输出map容器内容
    for (const auto& pair : myMap) {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }

    // 创建并初始化multimap容器
    std::multimap<int, std::string> myMultimap = {
        {1, "Apple"},
        {2, "Banana"},
        {2, "Orange"}
    };

    // 查找和访问multimap中的元素
    // 使用equal_range函数查找键为2的元素
    auto range = myMultimap.equal_range(2);
    for (auto it = range.first; it != range.second; ++it) {
        std::cout << "Element with key 2 found: " << it->second << std::endl;
    }

    return 0;
}

(4)遍历容器的所有元素:

#include <iostream>
#include <map>
#include <unordered_map>

int main() {
    // 创建并初始化map容器
    std::map<int, std::string> myMap = {
        {1, "One"},
        {2, "Two"},
        {3, "Three"}
    };

    // 遍历map容器的所有元素
    std::cout << "Iterating through map:" << std::endl;
    for (const auto& pair : myMap) {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }

    // 创建并初始化multimap容器
    std::multimap<int, std::string> myMultimap = {
        {1, "Apple"},
        {2, "Banana"},
        {2, "Orange"}
    };

    // 遍历multimap容器的所有元素
    std::cout << "\nIterating through multimap:" << std::endl;
    for (const auto& pair : myMultimap) {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }

    return 0;
}

3.3、性能分析

map和multimap都是关联容器,它们都基于红黑树实现。它们之间的主要区别在于:

  • map中的每个键都是唯一的,而multimap允许多个具有相同键的元素存在。
  • multimap中的元素在树中是按键值排序的,而map中的元素则按照键的比较函数进行排序。

从性能上来说,map通常比multimap具有更好的性能,因为map中的键是唯一的,可以更快地进行查找和访问操作。

如何选择:

  • 要保持键的唯一性,应该选择map。
  • 要允许多个具有相同键的元素存在,那么就应该选择multimap。

四、map和multimap容器的高级操作

(1)自定义比较函数和排序:在默认情况下,map和multimap容器使用元素的键值进行排序,但是有时候要根据不同的标准进行排序,这就需要自定义比较函数。

自定义比较函数需要满足严格弱顺序(Strict Weak Ordering)的要求:

  1. 反对称性:如果 a 不小于 b 且 b 不小于 a,则 a 等于 b。
  2. 传递性:如果 a 小于 b 且 b 小于 c,则 a 也小于 c。
  3. 可以相等:两个元素可以相等。

示例:

#include <iostream>
#include <map>
#include <string>

struct CustomCompare {
    bool operator() (const std::string& a, const std::string& b) const {
        // 根据字符串长度进行排序
        return a.length() < b.length();
    }
};

int main() {
    std::map<std::string, int, CustomCompare> myMap = {
        {"one", 1},
        {"three", 3},
        {"two", 2}
    };

    for (const auto& pair : myMap) {
        std::cout << pair.first << " : " << pair.second << std::endl;
    }

    return 0;
}

(2)处理重复键(multimap):遍历查找特定键的所有值。

std::multimap<int, std::string> myMultimap;
myMultimap.insert({1, "one"});
myMultimap.insert({2, "two"});
myMultimap.insert({1, "first"}); // 在键为1的位置再插入一个值

int keyToFind = 1;
auto range = myMultimap.equal_range(keyToFind);
for (auto it = range.first; it != range.second; ++it) {
    std::cout << it->first << " : " << it->second << std::endl;
}

(3)对map和multimap容器中的数据进行排序:

  1. 对 map 容器进行元素值排序:可以将 map 中的键值对元素复制到一个 vector 中,然后使用自定义的比较函数对 vector 进行排序:

    std::map<int, std::string> myMap = {
        {2, "two"},
        {1, "one"},
        {3, "three"}
    };
    
    std::vector<std::pair<int, std::string>> vec(myMap.begin(), myMap.end());
    std::sort(vec.begin(), vec.end(), 
              [](const std::pair<int, std::string>& a, const std::pair<int, std::string>& b) {
                  return a.second < b.second;
              });
    
  2. 对 multimap 容器进行元素值排序:由于 multimap 允许重复的键值,我们可以使用相似的方法将 multimap 中的元素复制到一个 vector 中,并使用自定义的比较函数对 vector 进行排序:

    std::multimap<int, std::string> myMultiMap = {
        {2, "two"},
        {1, "one"},
        {3, "three"},
        {2, "second"}
    };
    
    std::vector<std::pair<int, std::string>> vec(myMultiMap.begin(), myMultiMap.end());
    std::sort(vec.begin(), vec.end(), 
              [](const std::pair<int, std::string>& a, const std::pair<int, std::string>& b) {
                  return a.second < b.second;
              });
    

这样就可以使用自定义的比较函数对 map 和 multimap 容器中的元素值进行排序。在需要按照元素值而不是键值进行排序时,这些方法都比较有用。

五、代码实践

(1)map容器的使用。

#include <iostream>
#include <map>
#include <utility>
#include <string>
using namespace std;
class Person
{
        friend void test01();
        friend void printAll(map<int,Person> &m);
private:
        int num;
        string name;
        float score;
public:
        Person(){}
        Person(int num,string name,float score){
                this->num = num;
                this->name = name;
                this->score = score;
        }
};

void printAll(map<int,Person> &m)
{
        for(auto &[key,value]:m)
        {
                cout<<value.name<<","<<value.num<<","<<value.score<<endl;
        }
}

void test01(){
        map<int,Person> m;
                //方式1
        m.insert(pair<int,Person> (103,Person(103,"Lion",100.1)));
        // 方式二(推荐)
        m.insert(make_pair(102,Person(102,"Lion2",100.1)));
        // 方式三
        m.insert(map<int,Person>::value_type(101,Person(101,"Lion3",100.1)));
        // 方式四(危险)
        m[100]=Person(100,"FLY",100.1);
        printAll(m);

        // 演示方式四的危险性。
        cout<<"***********************"<<endl;
        cout<<m[107].name<<","<<m[107].num<<","<<m[107].score<<endl;
        printAll(m);
}
int main(int argc, char *argv[]){
        test01();
        return 0;
}

输出:

FLY,100,100.1
Lion3,101,100.1
Lion2,102,100.1
Lion,103,100.1
***********************
,0,0
FLY,100,100.1
Lion3,101,100.1
Lion2,102,100.1
Lion,103,100.1
,0,0

(2)multimap的示例。

#include <iostream>
#include <map>
#include <string>

int main() {
    // 创建一个 multimap 容器,键是 int 型,值是 string 型
    std::multimap<int, std::string> myMultiMap;

    // 向 multimap 中插入元素
    myMultiMap.insert(std::make_pair(1, "apple"));
    myMultiMap.insert(std::make_pair(2, "banana"));
    myMultiMap.insert(std::make_pair(3, "apple")); // 重复的键值

    // 遍历 multimap 并打印所有元素
    std::cout << "All elements in the multimap:" << std::endl;
    for (auto it = myMultiMap.begin(); it != myMultiMap.end(); ++it) {
        std::cout << it->first << " : " << it->second << std::endl;
    }

    // 查找特定键值对应的所有元素
    int keyToFind = 1;
    auto range = myMultiMap.equal_range(keyToFind);
    std::cout << "All elements with key " << keyToFind << ":" << std::endl;
    for (auto it = range.first; it != range.second; ++it) {
        std::cout << it->first << " : " << it->second << std::endl;
    }

    return 0;
}

总结

map和multimap是C++标准库中非常重要且常用的容器类型,它们都是关联式容器(Associative Containers),用于实现键值对映射。

  1. map和multimap容器使用红黑树实现,因此能够在O(log n)的时间复杂度内进行查找和检索操作,这使得它们非常适合于需要快速查找特定键值的应用场景。

  2. 这两种容器中的元素默认按照键值进行排序,map要求键值唯一,而multimap允许键值重复。这使得它们非常适合于建立有序的键值对映射,使得对数据的处理更加方便。

  3. 由于其快速查找和自动排序的特性,map和multimap容器可以应用于各种类型的问题,如数据存储、索引管理、关联规则等。

  4. map和multimap容器提供了各种方法来插入、删除和修改元素,同时它们还提供了丰富的迭代器接口和算法,对数据的操作更加灵活和方便。

【045】C++中map和multimap容器全面解析:深入学习,轻松掌握,C++从零开始到精通,c++,学习,开发语言,linux,服务器,C++11,map文章来源地址https://www.toymoban.com/news/detail-796092.html

到了这里,关于【045】C++中map和multimap容器全面解析:深入学习,轻松掌握的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C++STL——map/multimap容器详解

    纵有疾风起,人生不言弃。本文篇幅较长,如有错误请不吝赐教,感谢支持。 在STL中有些容器的元素是一种叫pair的数据结构。 对组(pair)是类模板,对组(pair)将一对值组合成一个值,一般用于表示key/value数据,这一对值可以具有不同的数据类型,两个值可以分别用pair的两个公

    2024年02月14日
    浏览(28)
  • 详解 C++中STL的map/multimap

    ap容器中所有元素都是pair,pair中第一个元素为key(键值),起到索引作用,第二个元素为value(实值)。 同时,所有元素都会根据元素的键值自动排序。 map/multimap属于关联式容器,底层数据结构是用二叉树实现的。它的优点就是可以根据key值快速找到value值。 这里需要了解map与

    2024年02月16日
    浏览(33)
  • 【C++入门到精通】C++入门 —— map & multimap (STL)

    各位小伙伴们,在这个美好的中秋节来临之际,我衷心祝福你和你的家人度过一个幸福、团圆的时刻。愿明月的皎洁照耀你的每一天,团圆的月饼传递着我对你的思念和祝福。祝福你在中秋佳节里收获幸福与快乐,家庭和睦,心想事成。中秋快乐! 前面我们讲了C语言的基础

    2024年02月08日
    浏览(29)
  • 【高阶数据结构】map和set的介绍和使用 {关联式容器;键值对;map和set;multimap和multiset;OJ练习}

    关联式容器和序列式容器是C++ STL中的两种不同类型的容器。 关联式容器是基于键值对的容器 ,其中每个元素都有一个唯一的键值,可以通过键值来访问元素。关联式容器包括set、multiset、map和multimap。 序列式容器是基于元素序列的容器 ,其中元素按照一定的顺序排列,可以

    2024年02月11日
    浏览(32)
  • 【C++】map、set、multimap、multiset的介绍和使用

    我讨厌世俗,也耐得住孤独。 1. 之前所学的vector,list,deque等容器都是序列式容器,因为他们的底层数据结构都是线性的,并且数据结构中存储的都是元素数据本身,也就是单一的变量。 而下面所学的set、map、multimap、multiset等容器都是关联式容器,他们内部存储的不再是单

    2023年04月15日
    浏览(25)
  • 【C++】STL——set/multiset 和 map/multimap的使用

    在初阶阶段,我们已经接触过STL中的部分容器 比如:vector、list、deque、forward_list(C++11)等,这些容器统称为 序列式容器 ,因为其底层为线性序列的数据结构,里面存储的是元素本身。 而今天我们要学习的几个容器称为关联式容器,那什么是关联式容器?它与序列式容器有什

    2024年02月14日
    浏览(28)
  • C++:stl中set(multiset)和map(multimap)的介绍和使用

    本文主要从概念、常用接口和使用方法方面介绍set(multiset)和map(multimap)。 目录 一、概念介绍 1.关联式容器 2.键值对 3. 树形结构的关联式容器 二、set和multiset 1.set的介绍 2.set使用 1. set模板参数列表 2. set构造 3. set迭代器 4. set容量 5. set修改操作 6.set使用举例 3.multiset介绍 4.mul

    2024年02月08日
    浏览(28)
  • 【C++进阶04】STL中map、set、multimap、multiset的介绍及使用

    vector/list/deque… 这些容器统称为 序列式容器 因为其底层为线性序列的数据结构 里面存储的是元素本身 map/set… 这些容器统称为 关联式容器 关联式容器也是用来存储数据的 与序列式容器不同的是 其里面存储的是key, value结构的键值对 在数据检索时比序列式容器效率更高 “键

    2024年02月03日
    浏览(31)
  • ⚡【C++要笑着学】(31) 映射类:map 类 | pair 类型 (value_type) | map 的插入和遍历 | map 的 operator[] | multimap 类

        C++ 表情包趣味教程 👉 《C++要笑着学》 💭 写在前面: 本章我们继续讲解 STL,讲解 STL 的 map 类。我们将详细介绍 map 类的基础概念,包括 pair 类型(value_type)的应用和插入元素的方法。随后,我们将深入研究 Map 的遍历方式以及统计元素出现次数的几种方式。最后我

    2024年02月03日
    浏览(30)
  • 深入探究C++中的STL:容器、迭代器与算法全解析

    Standard Template Library:标准模板库 是一个基于泛型的C++类模板库由Alexander Stepanov于1994年开发 其目的是为了提供一致通用和高效的数据结构和算法,同时不限制用户所处理的数据类型和编程范式。STL的原型最初由Andrew Koenig和其它C++专家小组进行设计并在1995年C++标准委员会的推

    2024年02月05日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包