STL常用容器(8)--map/multimap容器

1 map/multimap基本概念

map的特性是,所有元素都会根据元素的键值自动排序。map所有的元素都是pair,同时拥有实值和键值,pair的第一元素被视为键值,第二元素被视为实值,map不允许两个元素有相同的键值。

我们可以通过map的迭代器改变map的键值吗?答案是不行,因为map的键值关系到map元素的排列规则,任意改变map键值将会严重破坏map组织。如果想要修改元素的实值,那么是可以的。

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

multimap和map的操作类似,唯一区别multimap键值可重复

map和multimap都是以红黑树为底层实现机制。



2 map/multimap常用API

2.1 map构造函数

map<T1, T2> mapTT;		//map默认构造函数: 
map(const map &mp);		//拷贝构造函数

2.2 map赋值操作

map& operator=(const map &mp);		//重载等号操作符
swap(mp);							//交换两个集合容器

2.3 map大小操作

size();			//返回容器中元素的数目
empty();		//判断容器是否为空

2.4 map插入数据元素操作

map.insert(...); //往容器插入元素,返回pair<iterator,bool>
map<int, string> mapStu;

// 第一种 通过pair的方式插入对象
mapStu.insert(pair<int, string>(3, "小张"));

// 第二种 通过pair的方式插入对象,推荐
mapStu.inset(make_pair(-1, "校长"));

// 第三种 通过value_type的方式插入对象
mapStu.insert(map<int, string>::value_type(1, "小李"));

// 第四种 通过数组的方式插入值
// 通过第四种方式插入,如果指定的key原本不存在,会生成一个指定值为key,其value为0的pair插入到容器中
mapStu[3] = "小刘";
mapStu[5] = "小王";

2.5 map删除操作

clear();			//删除所有元素
erase(pos);			//删除pos迭代器所指的元素,返回下一个元素的迭代器。
erase(beg,end);		//删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
erase(keyElem);		//删除容器中key为keyElem的对组。

2.6 map查找操作

find(key);				//查找键key是否存在,若存在,返回该键的元素的迭代器;/若不存在,返回map.end();
count(keyElem);			//返回容器中key为keyElem的对组个数。对map来说,要么是0,要么是1。对multimap来说,值可能大于1。
lower_bound(keyElem);	//返回第一个key>=keyElem元素的迭代器。
upper_bound(keyElem);	//返回第一个key>keyElem元素的迭代器。
equal_range(keyElem);	//返回容器中key与keyElem相等的上下限的两个迭代器。


3 案例

3.1 Key为内置数据类型

#include <iostream>
#include <map>
using namespace std;

void printMap(map<string, int> &M) 
{
    for (map<string, int>::iterator it = M.begin(); it != M.end(); ++it)
    {   
        cout << it->first << " " << it->second << endl;
    }   
}

int main()
{
    map<string,int> M;

    // 插入
    M.insert(make_pair("李四", 20));
    M.insert(make_pair("张三", 18));
    M.insert(make_pair("王五", 21));

    printMap(M);

    cout << "============" << endl;
    M.erase("李四");
    printMap(M);

    cout << "============" << endl;
    map<string, int>::iterator ret = M.find("张三");
    if (ret != M.end())
    {
    	cout << ret->first << " " << ret->second << endl;
    }
    else
    {
    	cout << "没有找到" << endl;
    }
    
    cout << "M.size() = " << M.size() << endl;

    return 0;
}

在这里插入图片描述


3.2 Key为自定义数据类型

3.2.1 指定排序规则

对于Key为自定义数据类型必须指定排序规则,否则无法构造map容器,因为map容器所有元素都会根据元素的键值自动被排序

指定排序规则的的方法:
方法一:在自定义数据类型中重载 " < " [bool operator<()]
方法二:写一个仿函数,指定排序规则,在构造map容器时使用

#include <iostream>
#include <map>
using namespace std;

struct Key
{
    int key1;
    int key2;
    int key3;

    // 方法一
    bool operator<(const Key& K) const
    {
        if (key1 == K.key1 && key2 == K.key2)   // 如果key1和key2都相当,以key3进行升序排列
        {
            return key3 < K.key3;
        }
        else
        {
            if (key1 == K.key1)                 // 如果key1相等, 以key2进行升序排列
            {
                return key2 < K.key2;
            }
            else
            {
               return key1 < K.key1;        // 都不相等, 以key1进行升序排列
            }
        }
    }
};

// 方法二
class myCompare
{
public:
    bool operator()(const Key& k1, const Key& k2)
    {
        if (k1.key1 == k2.key1 && k1.key2 == k2.key2)   // 如果key1和key2都相当,以key3进行降序排列
        {
            return k1.key3 > k2.key3;
        }
        else
        {
            if (k1.key1 == k2.key1)                 // 如果key1相等, 以key2进行降序排列
            {
                return k1.key2 > k2.key2;
            }
            else
            {
               return k1.key1 > k2.key1;        // 都不相等, 以key1进行降序排列
            }
        }
    }
};

int main()
{
    // 方法一的map的构造
    map<Key, int> M;

    // 方法二的map构造
    //map<Key, int, myCompare> M;
    
    Key k1;
    k1.key1 = 10; k1.key2 = 20; k1.key3 = 30;
            
    Key k2;
    k2.key1 = 10; k2.key2 = 20; k2.key3 = 15;
        
    Key k3; 
    k3.key1 = 10; k3.key2 = 15; k3.key3 = 15;
                
    Key k4; 
    k4.key1 = 1; k4.key2 = 15; k4.key3 = 15;
            
    M.insert(make_pair(k1, 1)); 
    M.insert(make_pair(k2, 2));
    M.insert(make_pair(k3, 3));
    M.insert(make_pair(k4, 4));

    // 方法一的打印
    for (map<Key, int>::iterator it = M.begin(); it != M.end(); ++it)
    {
        cout << it->first.key1 << " "
             << it->first.key2 << " "
             << it->first.key2 << " "
             << it->second << endl;
    }

    // 方法二的打印
#if 0
    for (map<Key, int, myCompare>::iterator it = M.begin(); it != M.end(); ++it)
    {
        cout << it->first.key1 << " " 
             << it->first.key2 << " " 
             << it->first.key2 << " "
             << it->second << endl;
    }
#endif

    return 0;
}

在这里插入图片描述

3.2.2 将自定义数据类型通过位域组成内置数据类型

#include <iostream>
#include <map>
using namespace std;

struct A
{
    // 通过位域将下面三个字段组成一个uint64_t类型的数据
    // 这样就不需要重载<号,或者使用仿函数指定排序规则了
    uint64_t b1:36;
    uint64_t b2:16;
    uint64_t b3:12;
};

int main()
{
    map<uint64_t, int> M;

    A a1; 
    a1.b1 = 12345; a1.b2 = 12; a1.b3 = 10; 

    A a2; 
    a2.b1 = 1234; a2.b2 = 11; a2.b3 = 15; 

    A a3; 
    a3.b1 = 123; a3.b2 = 0; a3.b3 = 0;

    M.insert(make_pair(*(uint64_t*)&a1, 1));
    M.insert(make_pair(*(uint64_t*)&a2, 2));
    M.insert(make_pair(*(uint64_t*)&a3, 3));

    for (map<uint64_t, int>::iterator it = M.begin(); it != M.end(); ++it)
    {   
        cout << it->second << endl;
    }   

    return 0;
}

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值