STL标准库-容器-map和multimap

摘要: 摘要: 技术在于交流、沟通,本文为博主原创文章转载请注明出处并保持作品的完整性

map与multimap为关联容器,结构如下

map底层实现依然是rb_tree 他的data可以改,但是key不能改,因此map仍然具有自动排序的功能

我们无法使用迭代器改变元素的key(const key),但是可以改变元素的data.

map的key必须独一无二,multimap的key可以重复

map的定义函数

  template <typename _Key, typename _Tp, typename _Compare = std::less<_Key>,
            typename _Alloc = std::allocator<std::pair<const _Key, _Tp> > >
    class map
    {
    public:
      typedef _Key                                          key_type;
      typedef _Tp                                           mapped_type;
      typedef std::pair<const _Key, _Tp>                    value_type;
      typedef _Compare                                      key_compare;
      typedef _Alloc                                        allocator_type;
      ...
}

参数1 class key 键值key

参数2 class T data

参数3 class compare 排序key的函数 默认为less() 升序

参数4 alloc 分配器



map的基本使用

一 定义

    //构造函数
    map<int, int> c;
    c[1] = 10;
    c[2] = 20;
    c[3] = 30;
    c[4] = 40;
    c[5] = 50;
    for(auto i : c)
    {
        cout<<"["<< i.first <<"] = " << i.second <<"  ";
    }
    cout << endl;

    //operator =
    map<int, int> c1;
    c1 = c;
    for(auto i : c)
    {
        cout<<"["<< i.first <<"] = " << i.second <<"  ";
    }
    cout << endl;


二 迭代器操作 map的迭代器就是红黑树的迭代器

    //迭代器操作
    /*
    map<int, int> c;
    c.insert({pair<int, int>(1,10),pair<int, int>(2,20),pair<int, int>(3,30),pair<int, int>(4,40),pair<int, int>(5,50),pair<int, int>(6,60)});
    */

    //begin()
    map<int, int>::iterator iter;
    iter = c.begin();
    cout<< "begin(): "<<"["<< iter->first <<"] = " << iter->second <<endl;

    //end()
    iter = c.end();
    iter--;
    cout<<"end(): " <<"["<< iter->first <<"] = " << iter->second <<endl;

    //rbegin()反向头迭代器
    map<int, int>::reverse_iterator riter;
    riter = c.rbegin();
    cout << "rbegin(): "<<"["<< riter->first <<"] = " << riter->second <<endl;

    //rend()反向头迭代器
    riter = c.rend();
    riter--;
    cout << "rend(): "<<"["<< riter->first <<"] = " << riter->second <<endl;

    //cbegin() const 迭代器 正向 头迭代器
    map<int, int>::const_iterator citer;
    citer = c.cbegin();
    cout << "cbegin(): "<<"["<< citer->first <<"] = " << citer->second <<endl;

    //cend() const 迭代器 反向 尾迭代器
    citer = c.cend();
    citer--;
    cout<< "cend(): "<<"["<< citer->first <<"] = " << citer->second <<endl;


三 容量

    //容量
    /*
     map<int, int> c;
     c.insert({pair<int, int>(1,10),pair<int, int>(2,20),pair<int, int>(3,30),pair<int, int>(4,40),pair<int, int>(5,50),pair<int, int>(6,60)});
     */
    //是否为kong
    cout << "empty: " << c.empty() <<endl;

    //元素个数
    cout << "size: " << c.size() <<endl;

    //最大容量
    cout << "max_size: " << c.max_size() <<endl;


四 基本操作

//基本操作
    /*
     map<int, int> c;
     c.insert({pair<int, int>(1,10),pair<int, int>(2,20),pair<int, int>(3,30),pair<int, int>(4,40),pair<int, int>(5,50),pair<int, int>(6,60)});
     */

    //operator[] 这个和其他容器的operator有些不同,如果[index] 的index(key) 在map中存在则直接返回该key对应的data ,如果不存在则想该位置插入默认值
    cout << "operator[]: " << c[1] << endl;
    cout << "operator[]: " << c[10] << endl; //这时你会发现 map自动插入一个c[10]
    for(auto i : c)
    {
        cout<<"["<< i.first <<"] = " << i.second <<"  ";
    }
    cout << endl;

    //at() 取data
    cout<< "at(): " << c.at(3) << endl;

    //插入insert() map 不允许key重复 插入重复key 不会报错但插入不成功
    c.insert(pair<int, int>(6, 15));
    cout <<"insetr(): ";
    for(auto i : c)
    {
        cout<<"["<< i.first <<"] = " << i.second <<"  ";
    }
    cout << endl;

    map<int, int> c_insert;
    map<int, int>::iterator insert_iter = c_insert.begin();
    c_insert.insert(insert_iter,pair<int, int>(100, 10000));
    cout <<"insetr(): ";
    for(auto i : c_insert)
    {
        cout<<"["<< i.first <<"] = " << i.second <<"  ";
    }
    cout << endl;

    //删除
    map<int,int>::iterator erase_iter = c.begin();
    c.erase(erase_iter);
    cout <<"erase(): ";
    for(auto i : c)
    {
        cout<<"["<< i.first <<"] = " << i.second <<"  ";
    }
    cout << endl;
    //指定下表删除
    c.erase(10);
    cout <<"erase(): ";
    for(auto i : c)
    {
        cout<<"["<< i.first <<"] = " << i.second <<"  ";
    }
    cout << endl;

    //指定元素删除
    erase_iter = c.find(6);
    if(erase_iter != c.end())
    {
        cout<<"found index: "<< erase_iter->first <<endl;
        c.erase(erase_iter);
    }
    else{
        cout<< "Not found" <<endl;
    }
    for(auto i : c)
    {
        cout<<"["<< i.first <<"] = " << i.second <<"  ";
    }
    cout << endl;

    //交换swap
    map<int, int> c_swap1;
    c_swap1.insert({pair<int, int>(1,10),pair<int, int>(2,20),pair<int, int>(3,30),pair<int, int>(4,40),pair<int, int>(5,50),pair<int, int>(6,60)});
    map<int, int> c_swap2;
    cout<<"swap() before: "<<endl;
    cout<<"c_swap1: ";
    for(auto i : c_swap1)
    {
        cout<<"["<< i.first <<"] = " << i.second <<"  ";
    }
    cout << endl;

    cout<<"c_swap2: ";
    for(auto i : c_swap2)
    {
        cout<<"["<< i.first <<"] = " << i.second <<"  ";
    }
    cout << endl;

    cout<<"swap() after: ";
    c_swap2.swap(c_swap1);
    cout<<"c_swap1: ";
    for(auto i : c_swap1)
    {
        cout<<"["<< i.first <<"] = " << i.second <<"  ";
    }
    cout << endl;

    cout<<"c_swap2: ";
    for(auto i : c_swap2)
    {
        cout<<"["<< i.first <<"] = " << i.second <<"  ";
    }
    cout << endl;

    //清除clear
    c_insert.clear();
    cout <<"clear(): ";
    for(auto i : c_insert)
    {
        cout<<"["<< i.first <<"] = " << i.second <<"  ";
    }
    cout << endl;

    //elements() 插入 如果存在什么也不做 如果不存在插入
    map<int, int>::iterator element_iter = c_swap2.begin();

    auto xxx = c_swap2.emplace(pair<int, int>(7,60));
    if(xxx.second)
    {
        cout << "不存在" <<endl;
    }
    else
    {
        cout<< "存在" <<endl;
    }
    cout <<"elements(): ";
    for(auto i : c_swap2)
    {
        cout<<"["<< i.first <<"] = " << i.second <<"  ";
    }
    cout << endl;

    //emplace_hint() 插入
    element_iter = c.emplace_hint(element_iter, pair<int, int>(7,60));
    cout <<"emplace_hint(): ";
    if(element_iter != c_swap2.end())
    {
        cout<< "存在" <<endl;
    }
    else{
        cout << "不存在" <<endl;
    }


五 操作函数

    //函数
    /*
     map<int, int> c;
     c.insert({pair<int, int>(1,10),pair<int, int>(2,20),pair<int, int>(3,30),pair<int, int>(4,40),pair<int, int>(5,50),pair<int, int>(6,60)});
     */
    //key_comp 返回key排序的函数 返回仿函数
    cout<<"key_comp(): " << c.key_comp()(1,2) <<endl; //会返回1  因为1<2
    cout<<"key_comp(): " << c.key_comp()(2,1) <<endl; //会返回0  因为2>1
    cout<<"key_comp(): " << c.key_comp()(1,1) <<endl; //会返回0  因为1=1

    //value_comp 返回取value和key数据包中的 取key函数 返回仿函数
    pair<int,int> value_comp_pair = *c.begin();
    iter = c.begin();
    cout << c.value_comp()(*iter++,value_comp_pair) << endl;


六 算法

//算法
    /*
     map<int, int> c;
     c.insert({pair<int, int>(1,10),pair<int, int>(2,20),pair<int, int>(3,30),pair<int, int>(4,40),pair<int, int>(5,50),pair<int, int>(6,60)});
     */
    //find()  指定key 返回对应pair
    cout <<"find(1): " << c.find(1)->second << endl;;

    //count()   key出现的次数
    cout <<"count(1): " << c.count(1)<< endl;;

    c.erase(4);

    //lower_bound 返回键值>=给定元素的第一个位置
    auto lower_boundObj = c.lower_bound(8);
    if(lower_boundObj->first)
        cout<<lower_boundObj->first<<endl;
    else
        cout<< "Not found lower_boundObj" << endl;

    for(auto i : c)
    {
        cout<<"["<< i.first <<"] = " << i.second <<"  ";
    }
    cout << endl;

    //upper_bound 返回键值>给定元素的第一个位置
    auto upper_boundObj = c.upper_bound(4);
    if(upper_boundObj->first)
        cout<<upper_boundObj->first<<endl;
    else
        cout<< "Not found upper_bound" << endl;

    for(auto i : c)
    {
        cout<<"["<< i.first <<"] = " << i.second <<"  ";
    }
    cout << endl;

    //equal_range()返回该元素所在区间(闭区间),返回值是一个pair<iterator, iterator>类型,first代表所在区间的起点迭代器,second表示所在区间的终点迭代器

    auto equal_rangeObj = c.equal_range(3);
    if(equal_rangeObj.first->first)
    {
        cout<<equal_rangeObj.first->first<<endl;
    }
    else
        cout<< "NOT equal_rangeObj.first" << endl;

    if(equal_rangeObj.second->second)
    {
        cout<<equal_rangeObj.second->first<<endl;
    }
    else
        cout<< "NOT second" << endl;


七 自定义比较函数 map 默认为升序 改为降序

class my_compare_
{
public:
    bool operator()(int a, int b)
    {
        return a > b;
    }
};

int main(int argc, char *argv[])
{
    map<int, int, my_compare_> c;
    c.insert({pair<int, int>(1,10),pair<int, int>(2,20),pair<int, int>(3,30),pair<int, int>(4,40),pair<int, int>(5,50),pair<int, int>(6,60)});
    for(auto i : c)
    {
        cout<<"["<< i.first <<"] = " << i.second <<"  ";
    }
    cout << endl;
    return 0;
}
时间: 2024-12-28 09:40:55

STL标准库-容器-map和multimap的相关文章

STL标准库-容器-set与multiset

摘要: 技术在于交流.沟通,转载请注明出处并保持作品的完整性. set与multiset关联容器 结构如下 set是一种关联容器,key即value,value即key.它是自动排序,排序特点依据key set的key不能相同.multiset的key相同.关联容器的查找效率要高于顺序容器很多很多. set和multiset不提供用来直接存取元素的任何操作函数,取值需要通过迭代器 一 定义 1.set/mulitiset以红黑树为底层结构,因此有元素自动排序的特性,排序是根据key,而set.m

STL标准库-容器-list

摘要: 技术在于交流.沟通,本文为博主原创文章转载请注明出处并保持作品的完整性. list 表示非连续的内存区域,并通过一对指向首尾元素的指针双向链接起来,从而允许向前和向后两个方向进行遍历.在list 的任意位置插入和删除元素的效率都很高. 它的结构 一 定义 头文件 #include <vector> #include <iostream> #include <list> using namespace std; int main(int argc, const c

STL标准库-容器-rb_tree

摘要: 摘要: 技术在于交流.沟通,本文为博主原创文章转载请注明出处并保持作品的完整性 红黑树,关联式容器底层实现(map set),在使用中基本运用不到,但是还是想了解一下他的运作方式 Red_Black tree是平衡二分搜寻树(balanced binary search tree),它是高度平衡的二叉树,这样有利于search和insert. 红黑树提供遍历,如果如果按正常规则(++iter)遍历,便能获得排序状态 如上图,你会发现返回迭代器头的begin()函数指向的是"5"

STL标准库-容器适配器

摘要: 技术在于交流.沟通,本文为博主原创文章转载请注明出处并保持作品的完整性 上一节介绍了仿函数适配器,这节主要介绍容器适配器和迭代器适配器的概念,其实容器适配器和迭代器其适配器就是封装了一些其他class的方法,非常好理解. 如果你想让一个calss拥有另一个class的功能,你都可以这样做:1.继承 2.包含 迭代器适配器 运用继承方式,实现适配功能,其实现与仿函数适配器相似. 容器适配器中主要运用的就是包含,即一个类含的一个成员变量是另一个类,本节简单介绍两个容器适配器 容器适配器 qu

STL标准库-容器-deque

摘要: 技术在于交流.沟通,本文为博主原创文章转载请注明出处并保持作品的完整性. deque双向开口可进可出的容器 我们知道连续内存的容器不能随意扩充,因为这样容易扩充别人那去 deque却可以,它创造了内存连续的假象. 其实deque由一段一段构成 ,他是分段连续,而不是内存连续 当走向段的尾端时候自动跳到下一段 所以支持迭代器++ 操作,自动跳到下一段的方法由operator++实现 deque每次扩充 申请一个段 一 定义 头文件 #include <deque> int main_0(

STL标准库-容器-vector

摘要: 技术在于交流.沟通,本文为博主原创文章转载请注明出处并保持作品的完整性. 我对向量容器vector的理解就是一个动态数组,内存连续,它是动态分配内存,且每次扩张的原来的二倍. 他的结构如下 一 定义 vector< 类型 > 标识符(最大容量,初始所有值) vector是一种类模板,那么他有很多行为与类相似 头文件 #include <vector> //a.定义 vector<typeName> v; vector<int> v; //b.拷贝构造

STL标准库-算法-常用算法

摘要: 摘要: 摘要: 技术在于交流.沟通,本文为博主原创文章转载请注明出处并保持作品的完整性 介绍11种STL标准库的算法,从这11种算法中总结一下算法的基本使用 1.accumulate() 累加 2.for_each() for一段区间 做你指定的行为 3.replace(), replace_if(), replace_copy() 替换函数 4.count(), count_if() 计数 5.find() 查找 6.sort() 排序 7.binary_search()查看元素是否在

参考C++STL标准库中对了的使用方法

http://www.cppblog.com/zhenglinbo/archive/2012/09/18/191170.html 参考:http://www.cppblog.com/zhenglinbo/archive/2012/09/18/191170.html 当然是使用c++中的STL 的queue啦.下面简要介绍一下使用方法. 1 准备工作 头文件 #include<queue> 2 声明和定义的方法.STL的队列是泛型模板,支持任何内置和构造类型. 比如对于刚才那个牛奶问题.我把状态

GEEK学习笔记— —STL容器map和multimap

简介 在头文件<map> 中定义 namespace std { template <typename Key, typename T, typename Compare = less<Key>, typename Allocator = allocator<pair<const Key,T> > > class map; template <typename Key, typename T, typename Compare = less