STL(二)map/multimap

map

Map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据 处理能力。由于这个特性,它完成有可能在我们处理一对一数据的时候,在编程上提供快速通道。这里说下map内部数据的组织,map内部自建一颗红黑树(一 种非严格意义上的平衡二叉树),这颗树具有对数据自动排序的功能,所以在map内部所有的数据都是有序的,后边我们会见识到有序的好处。

  • 增加和删除节点对迭代器的影响很小,除了那个操作节点,对其他的节点都没有什么影响。
  • 对于迭代器来说,可以修改实值,而不能修改key
  • 自动建立Key - value的对应。key 和 value可以是任意你需要的类型。

插入

  • pair
  • value_type
  • []

pair 和value_type正常插入,如果key相同则插入失败。insert返回pair<iterator,bool>,可判断插入结果。而[]是修改元素,如果key不存在则插入,如果存在则覆盖。

删除

erase

  • 根据key删除
  • 使用迭代器删除,遵循前闭后开原则

查找

find,返回iterator。查找成功则返回对应元素的迭代器,查找失败则等于end()

#include "stdafx.h"
#include "iostream"
using namespace std;
#include "map"
//遍历打印map
void print(map<int, string> & m) {
    for (map<int, string>::iterator it = m.begin(); it != m.end(); it++) {
        cout << it->first << " " << it->second.c_str() << endl;
    }
}
//打印insert返回结果
void printInsertResPair(pair<map<int, string>::iterator, bool>& p) {
    cout << "插入结果 " << p.second << " |" << p.first->first<<" "<<p.first->second.c_str() << endl;
}
//打印find返回结果
void printFindResIt(map<int,string>&m,map<int, string>::iterator& it) {
    if (it != m.end()) {
        cout << "查找成功 " << it->first << " " << it->second.c_str() << endl;
    }
    else {
        cout << "查找失败" << endl;
    }
}
int main()
{
    map<int, string> nameMap;
    cout << "-------insert(pair)方式插入-------" << endl;
    nameMap.insert(pair<int, string>(1, "a"));
    nameMap.insert(pair<int, string>(3, "c"));
    nameMap.insert(pair<int, string>(2, "b"));
    print(nameMap);
    cout << "-------insert(value_type)方式插入-------" << endl;
    pair<map<int, string>::iterator, bool> p;
    nameMap.insert(map<int, string>::value_type(4, "d"));
    p = nameMap.insert(map<int, string>::value_type(5, "e"));
    printInsertResPair(p);
    p = nameMap.insert(map<int, string>::value_type(5, "f"));
    printInsertResPair(p);
    print(nameMap);
    cout << "-------[]方式插入-------" << endl;
    nameMap[5] = "g";
    nameMap[6] = "h";
    nameMap[7] = "i";
    print(nameMap);
    cout << "-------查找-------" << endl;
    map<int, string>::iterator it;
    it=nameMap.find(5);
    printFindResIt(nameMap,it);
    it = nameMap.find(10);
    printFindResIt(nameMap, it);
    cout << "-------key删除-------" << endl;
    nameMap.erase(1);
    print(nameMap);
    cout << "-------迭代器删除(前闭后开)-------" << endl;
    it = nameMap.find(4);
    nameMap.erase(nameMap.begin(),it);
    print(nameMap);
    return 0;
}
案例1.png

multimap

标准库还定义了一个 multimap 容器,它与 map 类似,所不同的是它允许重复键。这个属性使得 multimap 比预想的要更有用:比如在电话簿中相同的人可以有两个以上电话号码,文件系统中可以将多个符号链接映射到相同的物理文件,或DNS服务器可以将几个URLs映射到相同的IP地址。

插入

multimap::insert()成员函数返回指向新插入元素的迭代指针,也就是 iterator(multimap::insert()总是能执行成功)。但是 map::insert() 返回 pair<iterator, bool>,此处 bool 值表示插入操作是否成功。

查找

  • find(k) 返回匹配的第一个元素的迭代器。如果需要获取所有匹配元素,则需要遍历再次判断。

    it = m.find("it");
    while (it!=m.end())
    {
      if (it->first == "it") {
        cout << it->first << " ";
        it->second.print();
        it++;
      }
      else {
        break;
      }
    }
    

  • equal_range(k) 该函数查找所有与 k 关联的值。返回迭代指针的 pair,它标记开始和结束范围。

    pair<multimap<string,Student>::iterator, multimap<string,Student>::iterator> pEqual=m.equal_range("it");
    for (multimap<string, Student>::iterator it = pEqual.first; it != pEqual.second;it++) {
      cout << it->first << " ";
      it->second.print();
    }
    

虽然 map 和 multimap 具有相同的接口,其重要差别在于重复键,设计和使用要区别对待。此外,还要注意每个容器里 insert()成员函数的细微差别。

#include "stdafx.h"
#include "iostream"
#include "string"
#include "map"
using namespace std;

class Student {
private:
    string name;
    int number;
public:
    Student(int number, string name) {
        cout << "构造" << number << endl;
        this->number = number;
        this->name = name;
    }
    Student(const Student& student) {
        cout << "拷贝构造" << student.getNumber()<<" "<<student.getName().c_str() << endl;
        this->number = student.getNumber();
        this->name = student.getName();
    }

    void print()const {
        cout << this->number << " " << this->name << endl;
    }

    string getName()const {
        return this->name;
    }

    int getNumber()const {
        return this->number;
    }
};

void print(multimap<string, Student>& map) {
    for (multimap<string, Student>::iterator it=map.begin(); it != map.end(); it++) {
        cout << it->first.c_str() << " ";
        it->second.print();
    }
}
int main()
{
    multimap<string, Student> m;
    Student stu1(1, "a");
    cout << "--------------" << endl;
    //Student会执行拷贝构造
    pair<string, Student> p = pair<string, Student>("it", stu1);
    cout << "--------------" << endl;
    //Student会再一次执行拷贝构造
    m.insert(p);
    cout << "--------------" << endl;
    m.insert(pair<string, Student>("it", Student(2, "b")));
    m.insert(pair<string, Student>("sale", Student(3, "c")));
    m.insert(pair<string, Student>("product", Student(4, "d")));
    cout << "-------遍历插入结果-------" << endl;
    print(m);
    int count=m.count("it");
    cout << "cout(\"it\")=" << count << endl;
    multimap<string, Student>::iterator it;
    cout << "-------find(\"it\")查找单个值-------" << endl;
    it = m.find("it");
    while (it!=m.end())
    {
        if (it->first == "it") {
            cout << it->first << " ";
            it->second.print();
            it++;
        }
        else {
            break;
        }
    }
    cout << "-------equal_range处理多个关联值-------" << endl;
    pair<multimap<string,Student>::iterator, multimap<string,Student>::iterator> pEqual=m.equal_range("it");
    for (multimap<string, Student>::iterator it = pEqual.first; it != pEqual.second;it++) {
        cout << it->first << " ";
        it->second.print();
    }
    cout << "-------size-------" << endl;
    cout << m.size() << endl;
    return 0;
}
案例2.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容