C++STL之map与multimap的使用

/*
map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,
第二个可能称为该关键字的值)的数据处理能力,由于这个特性,它完成有可能在我们处理一对一数据的时候,
在编程上提供快速通道。这里说下map内部数据的组织,map内部自建一颗红黑树(一种非严格意义上的平衡二叉树),
这颗树具有对数据自动排序的功能,所以在map内部所有的数据都是有序的,后边我们会见识到有序的好处。
下面举例说明什么是一对一的数据映射。比如一个班级中,每个学生的学号跟他的姓名就存在着一一映射的关系,
这个模型用map可能轻易描述,很明显学号用int描述,姓名用字符串描述(本篇文章中不用char *来描述字符串,
而是采用STL中string来描述), 下面给出map描述代码:
[cpp] view plain copy
map<int, string> mapStudent;
*/
//1.map的构造函数
//map共提供了6个构造函数,这块涉及到内存分配器这些东西,略过不表,在下面我们将接触到一些map的构造方法,
//这里要说下的就是,我们通常用如下方法构造一个map:
//[cpp] view plain copy
//map<int, string> mapStudent;
//2.数据的插入
//在构造map容器后,我们就可以往里面插入数据了。这里讲三种插入数据的方法:
//第一种:用insert函数插入pair数据,下面举例说明(以下代码虽然是随手写的,
//应该可以在VC和GCC下编译通过,大家可以运行下看什么效果,在VC下请加入这条语句,
//屏蔽4786警告  #pragmawarning (disable:4786))
//[cpp] view plain copy

#include <map>  
#include <string>  
#include <iostream>  
using namespace std;
int main()
{
    map<int, string> mapStudent;//pair<int,string>p;p=make_pair(v1,v2);<span style="color: rgb(255, 0, 0);
    //background-color: rgb(240, 248, 255); font-family: Arial; font-size: 13px; "> </span>  
    mapStudent.insert(pair<int, string>(1, "student_one"));
    mapStudent.insert(pair<int, string>(2, "student_two"));
    mapStudent.insert(pair<int, string>(3, "student_three"));
    map<int, string>::iterator  iter;
    for (iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
    {
        cout << iter->first << "  " << iter->second << endl;
    }
}

//[cpp] view plain copy
//make_pair()//返回类型为对应的pair类型  
//无需写出类别,就可以生成一个pair对象
//例:
//make_pair(1, '@')
//而不必费力的写成
//pair<int, char>(1, '@')
//第二种:用insert函数插入value_type数据,下面举例说明
//[cpp] view plain copy
#include <map>  
#include <string>  
#include <iostream>  
using namespace std;
int main()
{
    map<int, string> mapStudent;
    mapStudent.insert(map<int, string>::value_type(1, "student_one"));
    mapStudent.insert(map<int, string>::value_type(2, "student_two"));
    mapStudent.insert(map<int, string>::value_type(3, "student_three"));
    map<int, string>::iterator  iter;
    for (iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
    {
        cout << iter->first << " " << iter->second << endl;
    }
}
//第三种:用数组方式插入数据,下面举例说明
//[cpp] view plain copy
#include <map>  
#include <string>  
#include <iostream>  
using namespace std;
int main()
{
    map<int, string> mapStudent;
    mapStudent[1] = "student_one";
    mapStudent[2] = "student_two";
    mapStudent[3] = "student_three";
    map<int, string>::iterator  iter;
    for (iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
    {
        cout << iter->first << "   " << iter->second << endl;
    }
}
//以上三种用法,虽然都可以实现数据的插入,但是它们是有区别的,当然了第一种和第二种在效果上是完成一样的,
//用insert函数插入数据,在数据的插入上涉及到集合的唯一性这个概念,即当map中有这个关键字时,
//insert操作是插入数据不了的,但是用数组方式就不同了,它可以覆盖以前该关键字对应的值,用程序说明
//[cpp] view plain copy
//mapStudent.insert(map<int, string>::value_type(1, "student_one"));
//mapStudent.insert(map<int, string>::value_type(1, "student_two"));
//上面这两条语句执行后,map中1这个关键字对应的值是"student_one",第二条语句并没有生效,
//那么这就涉及到我们怎么知道insert语句是否插入成功的问题了,可以用pair来获得是否插入成功,程序如下
//[cpp] view plain copy
//Pair<map<int, string>::iterator, bool> Insert_Pair;
//Insert_Pair = mapStudent.insert(map<int, string>::value_type(1, "student_one"));
//我们通过pair的第二个变量来知道是否插入成功,它的第一个变量返回的是一个map的迭代器,
//如果插入成功的话Insert_Pair.second应该是true的,否则为false。
//下面给出完成代码,演示插入成功与否问题
//[cpp] view plain copy
#include <map>  
#include <string>  
#include <iostream>  
using namespace std;
int main()
{
    map<int, string> mapStudent;
    pair<map<int, string>::iterator, bool> Insert_Pair;
    Insert_Pair = mapStudent.insert(pair<int, string>(1, "student_one"));
    if(Insert_Pair.second == true)
    {
        cout << "Insert Successfully" << endl;
    }
    else
    {
        cout << "Insert Failure" << endl;
    }
    Insert_Pair = mapStudent.insert(pair<int, string>(1, "student_two"));
    if(Insert_Pair.second == true)
    {
        cout << "Insert Successfully" << endl;
    }
    else
    {
        cout << "Insert Failure" << endl;
    }
    map<int, string>::iterator  iter;
    for (iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
    {
        cout << iter->first << "   " << iter->second << endl;
    }
}
//大家可以用如下程序,看下用数组插入在数据覆盖上的效果
//[cpp] view plain copy
#include <map>  
#include <string>  
#include <iostream>  
using namespace std;
int main()
{
    map<int, string> mapStudent;
    mapStudent[1] = "student_one";
    mapStudent[1] = "student_two";
    mapStudent[2] = "student_three";
    map<int, string>::iterator  iter;
    for (iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
    {
        cout << iter->first << "   " << iter->second << endl;
    }
}
//3.map的大小
//在往map里面插入了数据,我们怎么知道当前已经插入了多少数据呢,可以用size函数,用法如下:
//[cpp] view plain copy
//int nSize = mapStudent.size();
//4.数据的遍历
//这里也提供三种方法,对map进行遍
//第一种:应用前向迭代器,上面举例程序中到处都是了,略过不表
//第二种:应用反相迭代器,下面举例说明,要体会效果,请自个动手运行程序
//[cpp] view plain copy
#include <map>  
#include <string>  
#include <iostream>  
using namespace std;
int main()
{
    map<int, string> mapStudent;
    mapStudent.insert(pair<int, string>(1, "student_one"));
    mapStudent.insert(pair<int, string>(2, "student_two"));
    mapStudent.insert(pair<int, string>(3, "student_three"));
    map<int, string>::reverse_iterator  iter;
    for (iter = mapStudent.rbegin(); iter != mapStudent.rend(); iter++)
    {
        cout << iter->first << "   " << iter->second << endl;
    }
}
//第三种:用数组方式,程序说明如下
//[cpp] view plain copy
#include <map>  
#include <string>  
#include <iostream>  
using namespace std;
int main()
{
    map<int, string> mapStudent;
    mapStudent.insert(pair<int, string>(1, "student_one"));
    mapStudent.insert(pair<int, string>(2, "student_two"));
    mapStudent.insert(pair<int, string>(3, "student_three"));
    int nSize = mapStudent.size();
        //此处有误,应该是 for(int nIndex = 1; nIndex <= nSize; nIndex++)   
        //by rainfish  
    for (int nIndex = 0; nIndex < nSize; nIndex++)
    {
        cout << mapStudent[nIndex] << endl;
    }
}
//5.数据的查找(包括判定这个关键字是否在map中出现)
//在这里我们将体会,map在数据插入时保证有序的好处。
//要判定一个数据(关键字)是否在map中出现的方法比较多,这里标题虽然是数据的查找,在这里将穿插着大量的map基本用法。
//这里给出三种数据查找方法
//第一种:用count函数来判定关键字是否出现,其缺点是无法定位数据出现位置, 由于map的特性,一对一的映射关系,
//就决定了count函数的返回值只有两个,要么是0,要么是1,出现的情况,当然是返回1了
//第二种:用find函数来定位数据出现位置,它返回的一个迭代器,当数据出现时,它返回数据所在位置的迭代器,
//如果map中没有要查找的数据,它返回的迭代器等于end函数返回的迭代器,程序说明
//[cpp] view plain copy
#include <map>  
#include <string>  
#include <iostream>  
using namespace std;
int main()
{
    map<int, string> mapStudent;
    mapStudent.insert(pair<int, string>(1, "student_one"));
    mapStudent.insert(pair<int, string>(2, "student_two"));
    mapStudent.insert(pair<int, string>(3, "student_three"));
    map<int, string>::iterator iter;
    iter = mapStudent.find(1);
    if (iter != mapStudent.end())
    {
        cout << "Find, the value is " << iter->second << endl;
    }
    else
    {
        cout << "Do not Find" << endl;
    }
}
//第三种:这个方法用来判定数据是否出现,是显得笨了点,但是,我打算在这里讲解
//Lower_bound函数用法,这个函数用来返回要查找关键字的下界(是一个迭代器)
//Upper_bound函数用法,这个函数用来返回要查找关键字的上界(是一个迭代器)
//例如:map中已经插入了1,2,3,4的话,如果lower_bound(2)的话,返回的2,而upper - bound(2)的话,返回的就是3
//Equal_range函数返回一个pair,pair里面第一个变量是Lower_bound返回的迭代器,pair里面第二个
//迭代器是Upper_bound返回的迭代器,如果这两个迭代器相等的话,则说明map中不出现这个关键字,程序说明
//[cpp] view plain copy
#include <map>  
#include <string>  
#include <iostream>  
using namespace std;
int main()
{
    map<int, string> mapStudent;
    mapStudent[1] = "student_one";
    mapStudent[3] = "student_three";
    mapStudent[5] = "student_five";
    map<int, string>::iterator  iter;
    iter = mapStudent.lower_bound(2);
    {
        //返回的是下界3的迭代器  
        cout << iter->second << endl;
    }
    iter = mapStudent.lower_bound(3);
    {
        //返回的是下界3的迭代器  
        cout << iter->second << endl;
    }
    iter = mapStudent.upper_bound(2);
    {
        //返回的是上界3的迭代器  
        cout << iter->second << endl;
    }
    iter = mapStudent.upper_bound(3);
    {
        //返回的是上界5的迭代器  
        cout << iter->second << endl;
    }
    pair<map<int, string>::iterator, map<int, string>::iterator> mapPair;
    mapPair = mapStudent.equal_range(2);
    if (mapPair.first == mapPair.second)
    {
        cout << "Do not Find" << endl;
    }
    else
    {
        cout << "Find" << endl;
    }
    mapPair = mapStudent.equal_range(3);
    if (mapPair.first == mapPair.second)
    {
        cout << "Do not Find" << endl;
    }
    else
    {
        cout << "Find" << endl;
    }
}
//6.  数据的清空与判空
//清空map中的数据可以用clear()函数,判定map中是否有数据可以用empty()函数,它返回true则说明是空map
//7.  数据的删除
//这里要用到erase函数,它有三个重载了的函数,下面在例子中详细说明它们的用法
//[cpp] view plain copy
#include <map>  
#include <string>  
#include <iostream>  
using namespace std;
int main()
{
    map<int, string> mapStudent;
    mapStudent.insert(pair<int, string>(1, "student_one"));
    mapStudent.insert(pair<int, string>(2, "student_two"));
    mapStudent.insert(pair<int, string>(3, "student_three"));
    //如果你要演示输出效果,请选择以下的一种,你看到的效果会比较好  
    //如果要删除1,用迭代器删除  
    map<int, string>::iterator iter;
    iter = mapStudent.find(1);
    mapStudent.erase(iter);
    //如果要删除1,用关键字删除  
    int n = mapStudent.erase(1);//如果删除了会返回1,否则返回0  
    //用迭代器,成片的删除  
    //一下代码把整个map清空  
    mapStudent.erase(mapStudent.begin(), mapStudent.end());
    //成片删除要注意的是,也是STL的特性,删除区间是一个前闭后开的集合  
    //自个加上遍历代码,打印输出吧  
}
//8.其他一些函数用法
//这里有swap, key_comp, value_comp, get_allocator等函数,感觉到这些函数在编程用的不是很多,
//略过不表,有兴趣的话可以自个研究
//9.排序
//这里要讲的是一点比较高深的用法了, 排序问题,STL中默认是采用小于号来排序的,
//以上代码在排序上是不存在任何问题的,因为上面的关键字是int型,它本身支持小于号运算,在一些特殊情况,
//比如关键字是一个结构体,涉及到排序就会出现问题,因为它没有小于号操作,insert等函数在编译的时候过不去,
//下面给出两个方法解决这个问题
//第一种:小于号重载,程序举例
//[cpp] view plain copy
#include <map>  
#include <string>  
using namespace std;
typedef struct tagStudentInfo
{
    int      nID;
    string   strName;
}StudentInfo, *PStudentInfo;  //学生信息  
int main()
{
    int nSize;
    //用学生信息映射分数  
    map<StudentInfo, int>mapStudent;
    map<StudentInfo, int>::iterator iter;
    StudentInfo studentInfo;
    studentInfo.nID = 1;
    studentInfo.strName = "student_one"
        mapStudent.insert(pair<StudentInfo, int>(studentInfo, 90));
    studentInfo.nID = 2;
    studentInfo.strName = "student_two";
    mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80));
    for (iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
        cout << iter->first.nID << endl << iter->first.strName << endl << iter->second << endl;
}
//以上程序是无法编译通过的,只要重载小于号,就OK了,如下:
//[cpp] view plain copy
typedef struct tagStudentInfo
{
    int      nID;
    string   strName;
    bool operator < (tagStudentInfo const& _A) const
    {
        //这个函数指定排序策略,按nID排序,如果nID相等的话,按strName排序  
        if(nID < _A.nID)  return true;
        if(nID == _A.nID) return strName.compare(_A.strName) < 0;
        return false;
    }
}StudentInfo, *PStudentInfo;  //学生信息  
//第二种:仿函数的应用,这个时候结构体中没有直接的小于号重载,程序说明
//[cpp] view plain copy
#include <map>  
#include <string>  
using namespace std;
typedef struct tagStudentInfo
{
    int      nID;
    string   strName;
}StudentInfo, *PStudentInfo;  //学生信息  
class sort
{
public:
    bool operator() (StudentInfo const &_A, StudentInfo const &_B) const
    {
        if(_A.nID < _B.nID) return true;
        if(_A.nID == _B.nID) return _A.strName.compare(_B.strName) < 0;
        return false;
    }
};
int main()
{
    //用学生信息映射分数  
    map<StudentInfo, int, sort>mapStudent;
    StudentInfo studentInfo;
    studentInfo.nID = 1;
    studentInfo.strName = "student_one";
    mapStudent.insert(pair<StudentInfo, int>(studentInfo, 90));
    studentInfo.nID = 2;
    studentInfo.strName = "student_two";
    mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80));
}
//10.另外
//由于STL是一个统一的整体,map的很多用法都和STL中其它的东西结合在一起,比如在排序上,
//这里默认用的是小于号,即less<>,如果要从大到小排序呢,这里涉及到的东西很多,在此无法一一加以说明。
//还要说明的是,map中由于它内部有序,由红黑树保证,因此很多函数执行的时间复杂度都是log2N的,
//如果用map函数可以实现的功能,而STL  Algorithm也可以完成该功能,建议用map自带函数,效率高一些。
//下面说下,map在空间上的特性,否则,估计你用起来会有时候表现的比较郁闷,
//由于map的每个数据对应红黑树上的一个节点,这个节点在不保存你的数据时,是占用16个字节的,
//一个父节点指针,左右孩子指针,还有一个枚举值(标示红黑的,相当于平衡二叉树中的平衡因子),
//我想大家应该知道,这些地方很费内存了。
/*
multimap 类

标准模板库多重映射类用于存储和检索集合中的数据,此集合中的每个元素均为包含数据值和排序键的元素对。 
键值不需要唯一,用于自动排序数据。 可以直接更改多重映射中的元素值,但不能直接更改其关联键值。
必须先删除与旧元素关联的键值,才能插入与新元素关联的新键值。

语法
template <
    class Key,
    class Type,
    class Traits = less<Key>,
    class Allocator = allocator<pair <const Key, Type> >
> class multimap;
    参数
        Key
        要存储在多重映射中的键数据类型。

        Type
        要存储在多重映射中的元素数据类型。

        Traits
        一种提供函数对象的类型,该函数对象可将两个元素值作为排序键进行比较,以确定其在多重映射中的相对顺序。 默认值是二元谓词 less<Key>。

        在 C++ 14 中可以通过指定没有类型参数的 std::less<> 或 std::greater<> 谓词来启用异类查找。 有关详细信息,请参阅8e915ca1 - 19ba - 4f0d - 93c8 - e2c3bfd638eb#sequence_containers

        Allocator
        一种表示存储的分配器对象的类型,该分配器对象封装有关映射的内存分配和解除分配的详细信息。 此参数为可选参数,默认值为 allocator<pair <const Key, Type> >。

        备注
        STL 多重映射类是:

        大小可变的关联容器,支持基于关联键值高效检索元素值。

        可逆,因为它提供双向迭代器来访问其元素。

        有序,因为它的元素在容器中根据指定的比较函数按键值排序。

        多个,它的元素不需要具有唯一键,因此一个键值可具有多个相关联的元素数据值。

        关联容器对,因为它的元素数据值与其键值不同。

        模板类,因为它提供的功能是一般性的功能,因此与作为元素或键包含的特定数据类型无关。
        用于元素和键的数据类型作为类模板以及比较函数和分配器中的参数指定。

        映射类提供的迭代器是双向迭代器,但类成员函数 insert 和 multimap 具有将较弱输入迭代器作为模板参数的版本,
        较弱输入迭代器的功能要求比双向迭代器类保证的功能要求更少。 不同的迭代器概念形成一个系列,
        通过它们的功能优化相关联。 每个迭代器概念有它自己的一套要求,
        使用这些概念的算法必须根据迭代器类型提供的要求限制它们的假设。 可以假定输入迭代器可取消引用以引用某个对象,
        并可递增到序列中的下一迭代器。 这是最小的功能集,
        但足以按有意义的方式提供类成员函数的上下文中的迭代器范围[First, Last)。

        容器类型选择通常应根据应用程序所需的搜索和插入的类型。 关联容器针对查找、插入和移除操作进行了优化。
        显式支持这些操作的成员函数较为高效,执行这些操作的时间与容器中元素数量的对数平均成比例。
        插入元素不会使迭代器失效,移除元素仅会使专门指向已移除元素的迭代器失效。

        当应用程序满足将值与其键关联的条件时,应选择多重映射作为关联容器。 此类结构的模型是关键字排序列表,
        这些关键字具有提供定义等的关联字符串值,并且并非始终唯一定义。 如果关键字经过唯一定义以使键唯一,
        则应选择映射作为容器。 另一方面,如果仅存储关键字列表,则应使用集作为正确容器。 如果允许关键字多次出现,
        则应使用多重集合作为适当的容器结构。

        多重映射通过调用存储的 key_compare 类型的函数对象,对它控制的序列进行排序。 此存储的对象是比较函数,
        可通过调用成员函数 key_comp 访问。 通常,元素仅需小于比较元素即可建立此顺序;因此,给定任意两个元素,
        可以确定这两个元素等效(即两者均不小于对方)或其中一个小于另一个。 这将导致在非等效元素之间进行排序。
        在技术性更强的说明中,比较函数是一个二元谓词,在标准数学的意义上引发严格弱排序。 二元谓词 f(x, y) 
        是包含两个参数对象(x 和y)以及一个返回值(true 或 false)的函数对象。 如果二元谓词具有自反性、
        反对称性和传递性且等效可传递,对集进行的排序将为严格弱排序,其中两个对象x 和 y 定义为在 f(x, y) 
        和 f(y, x) 均为 false 时等效。 如果键之间的更强相等条件取代了等效性,则排序将为总排序(即所有元素彼此排序),
        并且匹配的键将难以彼此辨别。

        在 C++ 14 中可以通过指定没有类型参数的 std::less<> 或 std::greater<> 谓词来启用异类查找。
        有关详细信息,请参阅8e915ca1 - 19ba - 4f0d - 93c8 - e2c3bfd638eb#sequence_containers

        成员
        构造函数
        multimap

        构造一个空的或者是其他某个 multimap 的全部或部分副本的 multimap。

        Typedef
        allocator_type

        一种类型,此类型表示 allocator 对象的 multimap 类。

        const_iterator

        一种类型,此类型提供可读取 const 中的 multimap 元素的双向迭代器。

        const_pointer

        一种类型,此类型提供指向 const 中的 multimap 元素的指针。

        const_reference

        一种类型,此类型提供对存储在 const 中的 multimap 元素的引用(用于读取和执行 const 操作)。

        const_reverse_iterator

        一种类型,此类型提供可读取 const 中的任何 multimap 元素的双向迭代器。

        difference_type

        一种有符号整数类型,此类型可用于表示 multimap 中迭代器指向的元素间范围内的元素数量。

        iterator

        一种类型,此类型提供引用同一 multimap 中的元素的两个迭代器之间的差异。

        key_compare

        一种提供函数对象的类型,该函数对象可比较两个排序键以确定 multimap 中两个元素的相对顺序。

        key_type

        一种类型,此类型描述组成 multimap 中每个元素的排序键对象。

        mapped_type

        一种类型,此类型表示存储在 multimap 中的数据类型。

        指针

        一种类型,此类型提供指向 const 中的 multimap 元素的指针。

        引用

        一种类型,此类型提供对存储在 multimap 中的元素的引用。

        reverse_iterator

        一种类型,此类型提供可读取或修改反向 multimap 中的元素的双向迭代器。

        size_type

        一种无符号整数类型,此类型提供指向 const 中multimap 元素的指针。

        value_type

        一种提供函数对象的类型,该函数对象可将两个元素作为排序键比较以确定它们在 multimap 中的相对顺序。

        成员函数
        begin

        返回一个迭代器,此迭代器用于发现 multimap 中的第一个元素。

        cbegin

        返回一个常量迭代器,此迭代器用于发现 multimap 中的第一个元素。

        cend

        返回一个常量迭代器,此迭代器用于发现 multimap 中最后一个元素之后的位置。

        清除

        清除 multimap 的所有元素。

        count

        返回 multimap 中其键与指定为参数的键匹配的元素数量。

        crbegin

        返回一个常量迭代器,此迭代器用于发现反向 multimap 中的第一个元素。

        crend

        返回一个常量迭代器,此迭代器用于发现反向 multimap 中最后一个元素之后的位置。

        emplace

        将就地构造的元素插入到 multimap。

        emplace_hint

        将就地构造的元素插入到 multimap,附带位置提示

        空

        测试 multimap 是否为空。

        end

        返回一个迭代器,此迭代器用于发现 multimap 中最后一个元素之后的位置。

        equal_range

        查找其中元素的键与指定值匹配的元素范围。

        erase

        从 multimap 中的指定位置移除一个元素或元素范围,或者移除与指定键匹配的元素。

        find

        返回一个迭代器,此迭代器用于发现 multimap 中其键与指定键等效的元素的第一个位置。

        get_allocator

        返回用于构造 allocator 的 multimap 对象的副本。

        插入

        将一个元素或元素范围插入到 multimap。

        key_comp

        检索用于对 multimap 中的键进行排序的比较对象副本。

        lower_bound

        返回一个迭代器,此迭代器指向 multimap 中其键等于或大于指定键的第一个元素。

        max_size

        返回 multimap 的最大长度。

        rbegin

        返回一个迭代器,此迭代器用于发现反向 multimap 中的第一个元素。

        rend

        返回一个迭代器,此迭代器用于发现反向 multimap 中最后一个元素之后的位置。

        size

        返回 multimap 中的元素数量。

        swap

        交换两个 multimap 的元素。

        upper_bound

        返回一个迭代器,此迭代器指向 multimap 中其键大于指定键的第一个元素。

        value_comp

        此成员函数返回一个函数对象,该函数对象可通过比较 multimap 中元素的键值来确定元素顺序。

        运算符
        operator =

        将一个 multimap 中的元素替换为另一 multimap 副本。

        要求
        标头:<map>

    命名空间: std

          (key, value) 对作为 pair 类型的对象存储在多重映射中。 此对类需要标头 <utility>,<map> 自动包括此标头。
          */


/**
*@File MultiMapDemo.cpp
*
*@Author: Bob
*
*@Create Time: 2016-12-1 11:57:06
*
*@Last Modify: Bob
*
*@Last Modify Time: 2016-12-1 11:57:06
*
*@Description:
*   multimap多重映照容器
*   multimap多重映照容器:容器的数据结构采用红黑树进行管理
*    multimap的所有元素都是pair:第一元素为键值(key),不能修改;第二元素为实值(value),可被修改
*    multimap特性以及用法与map完全相同,唯一的差别在于:
*   允许重复键值的元素插入容器(使用了RB-Tree的insert_equal函数)
*   因此:
*      键值key与元素value的映照关系是多对多的关系
*      没有定义[]操作运算
*/

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



int main(int argc, char* argv[])
{
    std::multimap<std::string, int> myMultiMap;

    // 插入
    myMultiMap.insert(std::pair<std::string, int>("Jack", 1));
    myMultiMap.insert(std::pair<std::string, int>("Jack", 2));
    myMultiMap.insert(std::pair<std::string, int>("Bob", 1));
    myMultiMap.insert(std::pair<std::string, int>("Navy", 3));
    myMultiMap.insert(std::pair<std::string, int>("Demo", 4));
    myMultiMap.insert(std::pair<std::string, int>("Bob", 5));

    // 遍历
    std::cout << "================All member" << std::endl;
    for (std::multimap<std::string, int>::iterator iter = myMultiMap.begin(); iter != myMultiMap.end(); ++iter)
    {
        std::cout << (*iter).first << ":" << (*iter).second << std::endl;
    }


    // 统计key为"Jack"的数目
    std::string strFind = "Jack";
    unsigned int uCount = myMultiMap.count(strFind);
    if (uCount == 0)
    {
        std::cout << "================Count " << strFind << ":0" << std::endl;
    }
    else
    {
        std::cout << "================Count " << strFind << ":" << uCount << std::endl;
        std::multimap<std::string, int>::iterator iter = myMultiMap.find(strFind);
        if (iter != myMultiMap.end())
        {
            for (unsigned int i = 0; i < uCount; ++i)
            {
                std::cout << (*iter).first << ":" << (*iter).second << std::endl;
                iter++;
            }
        }
    }


    std::cout << "================use equal_range" << std::endl;
    typedef std::multimap<std::string, int>::iterator MultiMapIterator;
    std::pair<MultiMapIterator, MultiMapIterator> iterPair = myMultiMap.equal_range("Jack");
    for (MultiMapIterator it = iterPair.first; it != iterPair.second; ++it)
    {
        std::cout << (*it).first << ":" << (*it).second << std::endl;
    }


    // 删除所有key为"Bob"的键值对
    myMultiMap.erase("Bob");
    std::cout << "================After erase Bob" << std::endl;
    for (std::multimap<std::string, int>::iterator iter = myMultiMap.begin(); iter != myMultiMap.end(); ++iter)
    {
        std::cout << (*iter).first << ":" << (*iter).second << std::endl;
    }


    // 删除重复的key
    MultiMapIterator iter = myMultiMap.find("Jack");
    myMultiMap.erase(iter);
    std::cout << "================Use unique key, erase \"Jack\" " << std::endl;
    for (std::multimap<std::string, int>::iterator iter = myMultiMap.begin(); iter != myMultiMap.end(); ++iter)
    {
        std::cout << (*iter).first << ":" << (*iter).second << std::endl;
    }

    system("pause");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值