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<Key>,
            typename Allocator = allocator<pair<const Key,T> > >
        class multimap;
}

map和multimap都是有序关联容器,包含具有唯一键的键值对。键使用比较函数Compare比较来进行排序。搜索,删除和插入操作具有对数复杂性。map和multimap通常实现为红黑树。multimap相对map来说能够允许重复值的存在。

map和multimap操作

构造、复制与析构

map c //默认构造函数;创建一个空map/multimap

map c(op) //创建一个空map/multimap,并以op原则作为排序准则

map c(c2) //复制构造函数;创建一个新的map/multimap作为c2的副本(所有元素都被复制)

map c = c2 //复制构造函数;创建一个新的map作为c2的副本(所有元素都被复制)

map c(rv) //移动构造函数;使用右值对象rv创建一个新map/multimap

map c = rv //移动构造函数;使用右值对象rv创建一个新map/multimap

map c(beg,end) //创建一个map/multimap,并使用beg到end范围内的值进行初始化

map c(beg,end,op) //创建一个map/multimap,并使用beg到end范围内以op原则排序后的值进行初始化

map c(initlist) //创建一个map/multimap,并使用初始化列表进行初始化

map c = initlist //创建一个map/multimap,并使用初始化列表进行初始化

c.~map() //销毁所有元素并释放内存

在这里map可能是如下的一种:

map<Key,Val> //以less<>为排序准则的map

map<Key,Val,Op> //以op为排序准则的map

multimap<Key,Val> //以less<>为排序准则的multimap

multimap<Key,Val,Op> //以op为排序准则的multimap

非变动性操作

c.key_comp() //返回比较准则

c.value_comp() //返回对值比较的标准 (与
key_comp()相同)

c.empty() //判断容器是否为空,与size()==0相同,但可能更快

c.size() //返回当前元素数量

c.max_size() //返回可容纳的元素最大数量

c1 == c2 //判断c1与c2是否相等

c1 != c2 //判断c1与c2是否不相等,等同于!(c1==c2)

c1 < c2 //判断c1是否小于c2

c1 > c2 //判断c1是否大于c2

c1 <= c2 //判断c1是否小于等于c2

c1 >= c2 //判断c1是否大于等于c2

特殊查询操作

c.count(val) //返回值为val的元素个数

c.find(val) //返回第一个值为val的位置,若没找到返回end()

c.lower_bound(val) //返回val值的第一个可插入的位置,也就是元素值 >= val的第一个元素位置

c.upper_bound(val) //返回val值的最后一个可插入的位置,也就是元素值 > val的第一个元素位置

c.equal_range(val) //返回val值可插入的第一个位置和最后一个位置的区间,也就是元素值 == val的元素区间

赋值

c = c2 //将c2所有元素赋值给c

c = rv //将右值对象rv的所有元素移动赋值给c

c = initlist //使用初始化列表进行赋值

c1.swap(c2) //交换c1和c2的数

swap(c1,c2) //交换c1和c2的数

迭代器相关函数

c.begin() //返回一个双向迭代器,指向第一个元素

c.end() //返回一个双向迭代器,指向最后一个元素

c.cbegin() //返回一个双向常迭代器,指向第一个元素

c.cend() //返回一个双向常迭代器,指向最后一个元素

c.rbegin() //返回一个逆向迭代器,指向逆向迭代的第一个元素

c.rend() //返回一个逆向迭代器,指向逆向迭代的最后一个元素

c.crbegin() //返回一个逆向常迭代器,指向逆向迭代的第一个元素

c.crend() //返回一个逆向常迭代器,指向逆向迭代的最后一个元素

插入和移除元素

c.insert(val) //插入一个val的副本,返回新元素位置(对map来说不论成功与否)

c.insert(pos,val) //插入一个val副本,返回新元素位置(pos应该是插入的搜寻起点)

c.insert(beg,end) //将范围beg到end的所有元素的副本插入到c(无返回值)

c.insert(initlist) //插入初始化列表的所有元素的副本(无返回值)

c.emplace(args...) //插入一个使用args初始化的元素副本,返回新元素位置(对map来说不论成功与否)

c.emplace_hint(pos,args...) //插入一个使用args初始化的元素副本,返回新元素位置(pos应该是插入的搜寻起点)

c.erase(val) //移除所有与val值相等的元素,并返移除的元素个数

c.erase(pos) //移除迭代器位置的元素,并返回下个元素的位置

c.erase(beg,end) //移除beg到end范围内的所有元素,并返回下个元素的位置

c.clear() //移除所以元素,清空容器

键值对转递

//使用value_type
std::map<std::string,float> coll;

coll.insert(std::map<std::string,float>::value_type("otto",22.3));

//使用pair<>
std::map<std::string,float> coll;

coll.insert(std::pair<std::string,float>("otto",22.3));

//使用make_pair()
std::map<std::string,float> coll;

coll.insert(std::make_pair("otto",22.3));

当作关联数组使用

c[key] //返回一个指向键值为key的元素的引用,如果不存在就插入这个元素

c.at(key) //返回一个指向键值为key的元素的引用

栗子1

//使用算法和lambda

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

using namespace std;

int main()
{
    map<string,double> coll { { "tim", 9.9 }, { "struppi", 11.77 } };

    //对每个元素的值平方
    for_each (coll.begin(), coll.end(),
              [] (pair<const string,double>& elem)
              {
                  elem.second *= elem.second;
                });

    //输出元素
    for_each (coll.begin(), coll.end(),
              [] (const map<string,double>::value_type& elem)
              {
                  cout << elem.first << ": " << elem.second << endl;
                });

    return 0;
}

输出1

struppi: 138.533
tim: 98.01

栗子2

//当作关联数组使用

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

using namespace std;

int main()
{
    //创建map,键为string,值为float
    typedef map<string,float> StringFloatMap;
    StringFloatMap stocks;

    //插入元素
    stocks["BASF"] = 369.50;
    stocks["VW"] = 413.50;
    stocks["Daimler"] = 819.00;
    stocks["BMW"] = 834.00;
    stocks["Siemens"] = 842.20;

    //输出元素
    StringFloatMap::iterator pos;
    cout << left; //左对齐
    for (pos = stocks.begin(); pos != stocks.end(); ++pos)
    {
        cout << "stock: " << setw(12) << pos->first
             << "price: " << pos->second << endl;
    }
    cout << endl;

    //所有price翻一番
    for (pos = stocks.begin(); pos != stocks.end(); ++pos)
    {
        pos->second *= 2;
    }

    //输出元素
    for (pos = stocks.begin(); pos != stocks.end(); ++pos)
    {
        cout << "stock: " << setw(12) << pos->first
             << "price: " << pos->second << endl;
    }
    cout << endl;

    // 修改VM键为Volkswagen键
    stocks["Volkswagen"] = stocks["VW"];
    stocks.erase("VW");

    //输出元素
    for (pos = stocks.begin(); pos != stocks.end(); ++pos)
    {
        cout << "stock: " << setw(12) << pos->first
             << "price: " << pos->second << endl;
    }

    return 0;
}

输出2

stock: BASF price: 369.5
stock: BMW price: 834
stock: Daimler price: 819
stock: Siemens price: 842.2
stock: VW price: 413.5

stock: BASF price: 739
stock: BMW price: 1668
stock: Daimler price: 1638
stock: Siemens price: 1684.4
stock: VW price: 827

stock: BASF price: 739
stock: BMW price: 1668
stock: Daimler price: 1638
stock: Siemens price: 1684.4
stock: Volkswagen price: 827

栗子3

//作为字典使用

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

using namespace std;

int main()
{
    //创建multimap作为字典
    multimap<string,string> dict;

    //插入元素
    dict.insert ( { {"day","Tag"}, {"strange","fremd"},
        {"car","Auto"}, {"smart","elegant"},
        {"trait","Merkmal"}, {"strange","seltsam"},
        {"smart","raffiniert"}, {"smart","klug"},
        {"clever","raffiniert"}
        } );

    //输出元素
    cout.setf (ios::left, ios::adjustfield);
    cout << ‘ ‘ << setw(10) << "english "
         << "german " << endl;
    cout << setfill(‘-‘) << setw(20) << ""
         << setfill(‘ ‘) << endl;
    for ( const auto& elem : dict )
    {
        cout << ‘ ‘ << setw(10) << elem.first
             << elem.second << endl;
    }
    cout << endl;

    //输出所有smart键的值
    string word("smart");
    cout << word << ": " << endl;
    for (auto pos = dict.lower_bound(word);
            pos != dict.upper_bound(word);
            ++pos)
    {
        cout << " " << pos->second << endl;
    }

    //输出所以值为raffiniert的键
    word = ("raffiniert");
    cout << word << ": " << endl;
    for (const auto& elem : dict)
    {
        if (elem.second == word)
        {
            cout << " " << elem.first << endl;
        }
    }

    return 0;
}

输出3

english german
--------------------
car Auto
clever raffiniert
day Tag
smart elegant
smart raffiniert
smart klug
strange fremd
strange seltsam
trait Merkmal

smart:
elegant
raffiniert
klug
raffiniert:
clever
smart

栗子4

//查找

#include <map>
#include <iostream>
#include <algorithm>
#include <utility>
using namespace std;
int main()
{
    // 创建键与值都为float的map,并初始化
    map<float,float> coll = { {1,7}, {2,4}, {3,2}, {4,3},
        {5,6}, {6,1}, {7,3}
    };

    //查询一个key为3的元素,对数时间复杂度
    auto posKey = coll.find(3.0);
    if (posKey != coll.end())
    {
        cout << "key 3.0 found ("
             << posKey->first << ":"
             << posKey->second << ")" << endl;
    }

    //查询一个值为3的元素,线性时间复杂度
    auto posVal = find_if(coll.begin(),coll.end(),
                          [] (const pair<float,float>& elem)
    {
        return elem.second == 3.0;
    });

    if (posVal != coll.end())
    {
        cout << "value 3.0 found ("
             << posVal->first << ":"
             << posVal->second << ")" << endl;
    }

    return 0;
}

输出4

key 3.0 found (3:2)
value 3.0 found (4:3)

栗子5

//结合string,运行时排序

#include <iostream>
#include <iomanip>
#include <map>
#include <string>
#include <algorithm>
#include <cctype>

using namespace std;

//字符串比较函数,允许在运行事设置比较准则,允许在不分大小写的情况下比较
class RuntimeStringCmp
{
public:

    //比较标准常数
    enum cmp_mode {normal, nocase};
private:

    //实际比较模式
    const cmp_mode mode;

    //辅助函数,大小转化一致
    static bool nocase_compare (char c1, char c2)
    {
        return toupper(c1) < toupper(c2);
    }
public:

    //构造函数: 初始化比较准则
    RuntimeStringCmp (cmp_mode m=normal) : mode(m)
    {
    }

    //比较
    bool operator() (const string& s1, const string& s2) const
    {
        if (mode == normal)
        {
            return s1<s2;
        }
        else
        {
            return lexicographical_compare (s1.begin(), s1.end(),
                                            s2.begin(), s2.end(),
                                            nocase_compare);
        }
    }
};

typedef map<string,string,RuntimeStringCmp> StringStringMap;

//填充和输出函数
void fillAndPrint(StringStringMap& coll);

int main()
{
    //以默认比较准则创建容器
    StringStringMap coll1;
    fillAndPrint(coll1);

    //创建一个不区分大小写的比较对象
    RuntimeStringCmp ignorecase(RuntimeStringCmp::nocase);

    //创建一个不区分大小写的比较准则容器
    StringStringMap coll2(ignorecase);
    fillAndPrint(coll2);

    return 0;
}
void fillAndPrint(StringStringMap& coll)
{
    //插入元素
    coll["Deutschland"] = "Germany";
    coll["deutsch"] = "German";
    coll["Haken"] = "snag";
    coll["arbeiten"] = "work";
    coll["Hund"] = "dog";
    coll["gehen"] = "go";
    coll["Unternehmen"] = "enterprise";
    coll["unternehmen"] = "undertake";
    coll["gehen"] = "walk";
    coll["Bestatter"] = "undertaker";

    //输出元素
    cout.setf(ios::left, ios::adjustfield);
    for (const auto& elem : coll)
    {
        cout << setw(15) << elem.first << " "
             << elem.second << endl;
    }
    cout << endl;
}

输出5

Bestatter undertaker
Deutschland Germany
Haken snag
Hund dog
Unternehmen enterprise
arbeiten work
deutsch German
gehen walk
unternehmen undertake

arbeiten work
Bestatter undertaker
deutsch German
Deutschland Germany
gehen walk
Haken snag
Hund dog
Unternehmen undertake
时间: 2024-10-14 22:10:10

GEEK学习笔记— —STL容器map和multimap的相关文章

GEEK学习笔记— —STL容器之选用

默认情况下,选用vector,内部数据结构最简单,允许随机存取. 如果经常要在序列头部和尾部插入和删除元素,应该使用deque.如果希望元素被删除时,容器能自动缩减内存,那么也要选deque.此外,由于vector通常采用一个内存块存放元素,而deque采用多个内存块,后者可包含更多元素. 如果需要经常在容器中段执行元素的插入.删除或移动,可考虑list.list提供特殊成员函数,可在常数时间将元素从A容器转移到B容器.但由于list不支持随机存取,如果只知道list的头部却要访问中段元素,性能

GEEK学习笔记— —STL容器之无序容器(Unordered Container)

简介 在头文件<unordered_set>和<unordered_Unord> 中定义 namespace std { template <typename T, typename Hash = hash<T>, typename EqPred = equal_to<T>, typename Allocator = allocator<T> > class unordered_set; template <typename T

GEEK学习笔记— —STL容器list

简介 在头文件 <list> 中定义 namespace std { template <typename T, typename Allocator = allocator<T> > class list; } 列表是一个容器,它支持任何位置的元素快速插入和删除,不支持快速的随机访问.它被实现为双向的链表. 与forward_list相比,它提供双向迭代的能力,但空间效率更低. 插入和删除操作不会使指向其他元素指针.引用和迭代器失效. list操作 构造.复制与析构

GEEK学习笔记— —STL容器forward_list

简介 在头文件 <forward_forward_list> 中定义 namespace std { template <typename T, typename Allocator = allocator<T> > class forward_forward_list; } 单向列表是一个容器,支持在其任何地方快速插入和删除元素,不支持快速的随机访问.它被实现为单向链表,和C中它的实现相比,基本上不会有任何开销. 当不需要双向迭代的时候,与forward_list相比

C++学习笔记5 容器

1.  使用assign assign 操作首先删除容器中所有的元素,然后将其参数所指定的新元素插入到该容器中.与复制容器元素的构造函数一样,如果两个容器类型相同,其元 素类型也相同,就可以使用赋值操作符(=)将一个容器赋值给另一个容器.如果在不同(或相同)类型的容器内,元素类型不相同但是相互兼容,则其赋值运 算必须使用assign 函数.例如,可通过assign 操作实现将vector 容器中一段char* 类型的元素赋给string 类型list 容器. 由于assign 操作首先删除容器中

Go语言学习笔记十三: Map集合

Go语言学习笔记十三: Map集合 Map在每种语言中基本都有,Java中是属于集合类Map,其包括HashMap, TreeMap等.而Python语言直接就属于一种类型,写法上比Java还简单. Go语言中Map的写法比Java简单些,比Python繁琐. 定义Map var x map[string]string x : = make(map[string]string) 写法上有些奇怪,map为关键字,右侧中括号内部为key的类型,中括号外部为value的类型.一般情况下使用逗号或者冒号

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, typena

【C++ STL】Map和Multimap

1.结构 Map和multimap将key/value pair(键值/实值 队组)当作元素,进行管理.他们根据key的排序准则将元素排序.multimap允许重复元素,map不允许. 元素要求: key/value必须具有assigned(可赋值)和copyable(可复制的)性质. 对于排序而言,key必须具是comparable(可比较的). 2.能力 典型情况下,set,multisets,map,multimap使用相同的内部结构,因此可以将set和multiset当成特殊的map和m

STL容器 -- Map

核心描述: map 就是从键(key) 到 值(value) 的一个映射.且键值不可重复,内部按照键值排序. 头文件: #include <map> 拓展: multimap 是一个多重映照容器,键值可以重复.unordered_set 是一个内部不排序的映射容器,需包含头文件<unordered_map> 构造方法: map<int, string> kvm; //构造一个键为 int 型, 值为 string 型的 map 元素的插入: kvm[1] = "