zoukankan      html  css  js  c++  java
  • 09--STL关联容器(map/multimap)

    一:map/multimap的简介

    map是标准的关联式容器,一个map是一个键值对序列,即(key,value)对。它提供基于key快速检索能力
    map中key值是唯一的。集合中的元素按一定的顺序排列。元素插入过程是按排序规则插入,所以不能指定插入位置
    map的具体实现采用红黑树变体的平衡二叉树的数据结构。在插入操作和删除操作上比vector快(同set)
    map可以直接存取key所对应的value,支持[]操作符,如map[key]
    =value。

    multimap与map的区别:《重点》

    map支持唯一键值,每个键只能出现一次;
    multimap中相同键可以出现多次。
    multimap不支持[]操作符

    二:map/multimap对象的默认构造

    map/multimap采用模板类实现,对象的默认构造形式:
    
    map<T1,T2> mapTT;
    
    multimap<T1,T2>  multimapTT; 
    
    //其中T1,T2还可以用各种指针类型或自定义类型
    map<int, char> mapA;
    
    map<string,float> mapB;

    三:map对象的拷贝构造与赋值

    map(const map &mp);                   //拷贝构造函数
    
    map& operator=(const map &mp);         //重载等号操作符
    
    map.swap(mp);                                    //交换两个集合容器

    四:map排序方式

    map<T1,T2,less<T1>>  mapA;  //该容器是按键的升序方式排列元素。未指定函数对象,默认采用less<T1>函数对象。
    
    map<T1,T2,greater<T1>> mapB;   //该容器是按键的降序方式排列元素。
    less<T1>与greater<T1>可以替换成其它的函数对象functor。
    可编写自定义函数对象以进行自定义类型的比较,使用方法与set构造时所用的函数对象一样。

    五:map的插入操作《重点》

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

    在map中插入元素的四种方式:

    假设  map<int, string> mapStu;

    1、通过pair的方式插入对象

    mapStu.insert(pair<int,string>(3,"小张")  );

    2、通过pair的方式插入对象

    mapStu.inset(make_pair(-1, “校长-1”));

    3、通过value_type的方式插入对象

    mapStu.insert(  map<int,string>::value_type(1,"小李")  );

    前三种方法,采用的是insert()方法,该方法返回值为pair<iterator,bool>

     4、通过数组的方式插入值

    mapStu[3] = “小刘";
    
    mapStu[5] = “小王"

    第四种方法非常直观,但存在一个性能的问题:

    插入3时,先在mapStu中查找主键为3的项
    若没发现,则将一个键为3,值为初始化值的对组插入到mapStu中,然后再将值修改成“小刘”。
    若发现已存在3这个键,则修改这个键对应的value。
    string strName = mapStu[2];   //取操作或插入操作
    只有当mapStu存在2这个键时才是正确的取操作,否则会自动插入一个实例,键为2,值为初始化值。--->导致获取一个原来没有的键值

    六:map相关迭代函数

    map.begin();  //返回容器中第一个数据的迭代器。
    map.end();  //返回容器中最后一个数据之后的迭代器。
    map.rbegin();  //返回容器中倒数第一个元素的迭代器。
    map.rend();   //返回容器中倒数最后一个元素的后面的迭代器
    int main()
    {
        map<int, char> ma;
        pair<int, char> p;
    
        ma.insert(pair<int, char>(95, 'a'));
        ma.insert(pair<int, char>(63, 'A'));
    
        for (map<int, char>::iterator iter = ma.begin(); iter != ma.end();iter++)
        {
            p = *iter;
            cout << p.first << "=" << p.second << endl;
        }
    
        system("pause");
        return 0;
    }

    七:map对象大小

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

    八:map对象的删除

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

    九:map的查找操作

    map.find(key);   查找键key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回map.end();
    map.count(keyElem);   //返回容器中key为keyElem的对组个数。对map来说,要么是0,要么是1。对multimap来说,值可能大于1。

    十:性能测试

    #define _CRT_SECURE_NO_WARNINGS
    #include <iostream>
    #include <stdio.h>
    #include <cstring>
    
    #if _MSC_VER
    #define snprintf _snprintf
    #endif
    
    using namespace std;
    
    long get_a_target_long()
    {
        /******变量声明********/
        long target = 0;
        /**********************/
    
        cout << "targer (0~" << RAND_MAX << "):";
        cin >> target;
        return target;
    }
    
    string get_a_target_string()
    {
        /******变量声明********/
        long target = 0;
        char buf[10];
        /**********************/
    
        cout << "targer (0~" << RAND_MAX << "):";
        cin >> target;
    
        snprintf(buf, 10, "%d", target);
        return string(buf);
    }
    
    //与后面的比较函数中回调参数对应
    int compareLongs(const void* l1, const void* l2)
    {
        return (*(long*)l1 - *(long*)l2);
    }
    
    int compareStrings(const void* s1, const void* s2)
    {
        if (*(string*)s1 > *(string*)s2)
            return 1;
        if (*(string*)s1 < *(string*)s2)
            return -1;
        return 0;
    }
    公共函数

    (一) multimap测试

    #include <map>
    //测试multimap-->元素可以重复
    namespace jj09
    {
        void test_multimap(long& mm_size)
        {
            cout << "
    test_multimap()*******" << endl;
    
            /******变量声明:数组初始********/
            char buf[10];
    
            /******变量声明:multimap初始********/
            multimap<long, string> mm;
    
            /******变量声明:记录时间********/
            clock_t timeStart = clock();    //开始时间
            for (long i = 0; i < mm_size; i++)
            {
                try
                {
                    snprintf(buf, 10, "%d", rand());
                    mm.insert(pair<long, string>(i, string(buf)));
                }
                catch (exception& e)
                {
                    cout << e.what() << endl;
                    cout << "Max_size:" << i << endl;
                    abort();    //终止
                }
            }
    
            cout << "inti multimap use milli-seconds:" << (clock() - timeStart) << endl;    //获取初始化数组耗时
            cout << "multimap.size:" << mm.size() << endl;    //获取multimap大小
            cout << "multimap.max_size:" << mm.max_size() << endl;    //获取multimap所允许最大长度
    
            /******变量声明:获取我们要查询的数********/
            long target = get_a_target_long();    //根据key查找
    
    
            //multimap没有全局::find方法可用,::find找值,multimap找键,两者不同,不可以混用
    
    
            //使用muliset.find查找
            timeStart = clock();
    
            auto pI = mm.find(target);
    
            cout << "multimap.find(),milli-seconds:" << clock() - timeStart << endl;
            if (pI != mm.end())
                cout << "found:" << (*pI).first << ":" << (*pI).second << endl;
            else
                cout << "not found!" << endl;
    
        }
    }

    释放指针和寻址耗时,所以destroyc()操作耗时

    (二)map测试

    #include <map>
    //测试map-->元素不可以重复
    namespace jj11
    {
        void test_map(long& m_size)
        {
            cout << "
    test_map()*******" << endl;
    
            /******变量声明:数组初始********/
            char buf[10];
    
            /******变量声明:map初始********/
            map<long, string> m;
    
            /******变量声明:记录时间********/
            clock_t timeStart = clock();    //开始时间
            for (long i = 0; i < m_size; i++)
            {
                try
                {
                    snprintf(buf, 10, "%d", rand());
                    m.insert(pair<long, string>(i, string(buf)));
                }
                catch (exception& e)
                {
                    cout << e.what() << endl;
                    cout << "Max_size:" << i << endl;
                    abort();    //终止
                }
            }
    
            cout << "inti map use milli-seconds:" << (clock() - timeStart) << endl;    //获取初始化数组耗时
            cout << "map.size:" << m.size() << endl;    //获取map大小
            cout << "map.max_size:" << m.max_size() << endl;    //获取map允许最大长度
    
            /******变量声明:获取我们要查询的数********/
            long target = get_a_target_long();    //根据key查找
    
    
            //map没有全局::find方法可用,::find找值,map找键,两者不同,不可以混用
    
    
            //使用map.find查找
            timeStart = clock();
    
            auto pI = m.find(target);
    
            cout << "map.find(),milli-seconds:" << clock() - timeStart << endl;
            if (pI != m.end())
                cout << "found:" << (*pI).first << ":" << (*pI).second << endl;
            else
                cout << "not found!" << endl;
    
        }
    }

    这里由于在插入时key值不同,所以插入1000000个数据全部不相同,含有太多数据,所以destroy()操作费时
  • 相关阅读:
    【Leetcode】【Easy】Remove Duplicates from Sorted List
    【Leetcode】【Easy】Pascal's Triangle II
    【Leetcode】【Easy】Pascal's Triangle
    【Leetcode】【Easy】Binary Tree Level Order Traversal II
    【Leetcode】【Easy】Binary Tree Level Order Traversal
    【Leetcode】【Easy】Maximum Depth of Binary Tree
    【Leetcode】【Easy】Minimum Depth of Binary Tree
    【Leetcode】【Easy】Balanced Binary Tree
    【Leetcode】【Easy】Symmetric Tree
    如何使用Action.Invoke()触发一个Storyboard
  • 原文地址:https://www.cnblogs.com/ssyfj/p/10791537.html
Copyright © 2011-2022 走看看