c++STL库容器之map

map简介

Map是STL的一个关联容器,它的特点是增加和删除节点对迭代器的影响很小,除了那个操作节点,对其他的节点都没有什么影响。对于迭代器来说,可以修改实值,而不能修改key。它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力,由于这个特性,它完成有可能在我们处理一对一数据的时候,在编程上提供快速通道。这里说下map内部数据的组织,map内部自建一颗红黑树(一种非严格意义上的平衡二叉树),这颗树具有对数据自动排序的功能,所以在map内部所有的数据都是有序的,后边我们会见识到有序的好处。

Map初始化

(1) 默认构造: map<Key, value> m;  构造一个空的map,注意,必要时要给出模板参数中的 Compare。需要时给出 Alloc

(2) 范围构造: map<key, value> m(iterator first, iteratorlast);  将迭代器[frist, last)范围内的元素填入map中

(3) 拷贝构造: map<key, value> m(cosnt map& m2);  用m2构造m

(4) 初始化列表构造: map<key, value>m(initializer_list<value_type> il)

由于map 的 value_type 是 pair类型,所以要构造成pair作为列表,这是三种构造 pair的方式

map<key, value> m{{key k1,value v1},{k2, v2}, ...}  // 通过 {}构造 pair

map<key, value>m{make_pair(key k1, value v1), make_pair(k2, v2), ...}  // 通过make_pair() 函数构造 pair

map<key, value>m{pair<key, value>(k1, v1), pair<key, value>(k2, v2), ...}  // 通过类型转换构造pair

map常用函数

      begin()                 返回指向map头部的迭代器
      clear()                删除所有元素
      count()                 返回指定元素出现的次数
      empty()                如果map为空则返回true
      end()                    返回指向map末尾的迭代器
      equal_range()      返回特殊条目的迭代器对
      erase()                  删除一个元素
      find()                    查找一个元素
      get_allocator()     返回map的配置器
      insert()                  插入元素
      key_comp()          返回比较元素key的函数
      lower_bound()     返回键值>=给定元素的第一个位置
      max_size()            返回可以容纳的最大元素个数
      rbegin()               返回一个指向map尾部的逆向迭代器
      rend()                  返回一个指向map头部的逆向迭代器
      size()                    返回map中元素的个数
      swap()                 交换两个map
      upper_bound()     返回键值>给定元素的第一个位置
      value_comp()      返回比较元素value的函数

这里我们着重讲解erase函数

//测试erase函数
    map<int, int>::iterator it2 = mymap.begin();
    while(it2 != mymap.end())
    {
        if(it2->second == 12)
        {
            mymap.erase(it2++);
            /*
            该方法中利用了后缀++的特点,这个时候执行mapInt.erase(it2++);这条语句分为三个过程
            1、先把it2的值赋值给一个临时变量做为传递给erase的参数变量

            2、因为参数处理优先于函数调用,所以接下来执行了it2++操作,也就是it2现在已经指向了下一个地址。

            3、再调用erase函数,释放掉第一步中保存的要删除的it2的值的临时变量所指的位置。


            前缀++和后缀++的返回值一个是迭代器引用,一个却是迭代器传值.简单来说,
            前缀++返回的便是传参进来的迭代器,自然可以返回迭代器本身的引用,
            然而后缀++返回的是一个函数内部的临时变量,在函数执行完后便析构了,
            必然不能传引用。注意既然是通过传值的方式返回,对其返回值的修改对于原it2是没有影响的
            */
        }
        it2++;
    }
    print(mymap);

erase删除的是迭代器指向的数据。


还有find函数,函数原型是iterator find (const key_type& k); 返回值要用迭代器iterator接收

代码如下:

//测试find函数   函数原型 iterator find (const key_type& k);   返回值用迭代器接收
    map<int, int>::iterator it1 = mymap.find(1);
    cout << "返回元素" << it1->second << endl;


一个测试map函数的简单小程序

#include <iostream>
#include <map>

using namespace std;

//抽象一个print函数,用来打印map中的值
void print(map<int, int> mymap)
{
    map<int, int> ::iterator itor = mymap.begin();
    while(itor != mymap.end())
    {
        cout << "打印map的数据" << itor->first << " " << itor->second << endl;
        itor++;
    }
}

int main()
{
    map<int, int> mymap;
    cout << "初始化前map的大小: " << mymap.size() << endl;    //显示初始化前map的大小

    //赋值时故意key值没有按顺序输入,但是打印时确实按顺序输出,说明map内部有自带的排序的结构,即红黑树,这样给我们启示:查找数据会变得简单
    mymap[0] = 10;
    mymap[2] = 12;
    //mymap[1] = 11;
    mymap.insert(map<int, int>::value_type(1,11));
    /*
    以上赋值方法开销较大,不太好,如输入 mymap[1] = 11时,需要依次比较map中存在的key值,按大小进行插入。可以按照以下的方法进行赋值
        mymap.insert(map<int, int>::value_type(1,11));
    */

    cout << "初始化后map的大小:" << mymap.size() << endl;    ////显示初始化后map的大小

    //用迭代器遍历map的数据
    map<int, int> ::iterator itor = mymap.begin();
    while(itor != mymap.end())
    {
        //通过map对象的方法获取的iterator数据类型是一个std::pair对象,
        //包括两个数据 iterator->first 和 iterator->second 分别代表关键字和存储的数据
        cout << "打印map的数据" << itor->first << " " << itor->second << endl;
        itor++;
    }

    //以下代码用来测试map的相关函数
    /*
    mymap.clear();  //用来清除map中的所有元素
    cout << "调用clear函数之后map的大小" << mymap.size() << endl;
    */

    //测试find函数   函数原型 iterator find (const key_type& k);   返回值用迭代器接收
    map<int, int>::iterator it1 = mymap.find(1);
    cout << "返回元素" << it1->second << endl;

    //测试erase函数
    map<int, int>::iterator it2 = mymap.begin();
    while(it2 != mymap.end())
    {
        if(it2->second == 12)
        {
            mymap.erase(it2++);
            /*
            该方法中利用了后缀++的特点,这个时候执行mapInt.erase(it2++);这条语句分为三个过程
            1、先把it2的值赋值给一个临时变量做为传递给erase的参数变量

            2、因为参数处理优先于函数调用,所以接下来执行了it2++操作,也就是it2现在已经指向了下一个地址。

            3、再调用erase函数,释放掉第一步中保存的要删除的it2的值的临时变量所指的位置。


            前缀++和后缀++的返回值一个是迭代器引用,一个却是迭代器传值.简单来说,
            前缀++返回的便是传参进来的迭代器,自然可以返回迭代器本身的引用,
            然而后缀++返回的是一个函数内部的临时变量,在函数执行完后便析构了,
            必然不能传引用。注意既然是通过传值的方式返回,对其返回值的修改对于原it2是没有影响的
            */
        }
        it2++;
    }
    print(mymap);


    return 0;
}

运行结果为


猜你喜欢

转载自blog.csdn.net/young_Tao/article/details/79824791