c++ primer 【笔记】multimap 和 multiset类型

map 和 set 容器中,一个键只能对应一个实例。而 multiset 和 multimap类型则允许一个键对应多个实例。multimap 和 multiset 所支持的操作分别与 map 和 set 的操作相同,只有一个例外:multimap 不支持下标运算。不能对 multimap 对象使用下标操作,因为在这类容器中,某个键可能对应多个值。为了顺应一个键可以对应多个值这一性质,map 和 multimap,或 set 和 multiset 中相同的操作都以不同的方式做出了一定的修改。在使用 multimap 或 multiset 时,对于某个键,必须做好处理多个值的准备,而非只有单一的值。

元素添加和删除

insert 操作和 erase 操作同样适用于 multimap 和 multiset 容器,实现元素添加和删除。
由于键不要求是唯一的,因此每次调用 insert 总会添加一个元素。

//insert first element 
authors.insert(make_pair( string("Au"), string("book1")));
//insert second element
authors.insert(make_pair( string("Au"), string("book2")));

带有一个键参数的 erase 版本将删除拥有该键的所有元素,并返回删除元素的个数。而带有一个或一对迭代器参数的版本只删除指定的元素, 并返回 void类型。

元素删除
关联容器 map 和 set 的元素是按顺序存储的。而 multimap 和multset 也一样。因此,在 multimap 和 multiset 容器中,如果某个键对应多个实例,则这些实例在容器中将相邻存放。迭代遍历 multimap 或 multiset 容器时,可保证依次返回特定键所关联的所有元素。
在multimap 中查找元素有两种方法:
1. 使用find 和count操作
count 函数求出某键出现的次数, 而 find 操作则返回一个迭代器, 指向第一个拥有正在查找的键的实例,在后面展示的习题代码中有使用这种方法。
2. 使用关联容器 lower_bound 、upper_bound 和 equal_range。
表 1 返回迭代器的关联容器操作

m.lower_bound(k)返回一个迭代器,指向键不小于 k 的第一个元素
m.upper_bound(k)返回一个迭代器,指向键大于 k 的第一个元素
m.equal_range(k)返回一个迭代器的 pair 对象它的 first 成员等价于 m.lower_bound(k)。而 second 成员则等价于m.upper_bound(k)

*
若该键没有关联的元素,则 lower_bound 和 upper_bound 返回相同的迭代器:都指向同一个元素或同时指向 multimap 的超出末端位置。它们都指向在保持容器元素顺序的前提下该键应被插入的位置。
使用equal_range 的效果和 low_bound+upper_bound 的效果一样。调用 equal_range 函数来取代调用 upper_bound 和 lower_bound 函数。equal_range 函数返回存储一对迭代器的 pair 对象。如果该值存在,则 pair 对象中的第一个迭代器指向该键关联的第一个实例,第二个迭代器指向该键关联的最后一个实例的下一位置。如果找不到匹配的元素,则 pair 对象中的两个迭代器都将指向此键应该插入的位置。

习题程序代码
Exercise 10.26 编写程序建立作者及其作品的 multimap 容器。使用find 函数在multimap 中查找元素,并调用 erase 将其删除。当所寻找的元素不存在时,确保你的程序依然能正确执行。

Exercise 10.27 重复上一题所编写的程序,但这一次要求使用equal_range 函数获取迭代器,然后删除一段范围内的元素。

Exercise 10.28 沿用上题中的 multimap 容器,编写程序以下面的格式按姓名首字母的顺序输出作者名字:
Author Names Beginning with ‘A’:
Author, book, book, …

Author Names Beginning with ‘B’:

将以上三题编写到了一个程序中:

#include<iostream>
#include<fstream>
#include<map>
#include<algorithm>

using namespace std;
//open files
ifstream &open_file(ifstream &in, const string file){
    in.close();
    in.clear();
    in.open(file.c_str());
    return in;
}
//read files into multimap
void authors_works(ifstream &authorWorks, multimap<string, string> &links){
    string author, work;
    while(authorWorks >> author >> work)
        links.insert(make_pair(author, work));
}

int main(int argc, char *argv[]){
    ifstream authorWorks;
    multimap<string, string> links;
    if(argc < 2)
        throw range_error("NO files input!");
    if(!open_file(authorWorks, argv[1]))
        throw runtime_error("can not open file!");
    authors_works(authorWorks, links);

    string search_author;

    //search multimap by iterm using count and find
    cout << "Input your search author: ";
    cin >> search_author;
    typedef multimap<string, string>::size_type sz_type;
    typedef multimap<string, string>::iterator multi_iter;
    sz_type entries = links.count(search_author);
    multi_iter iter = links.find(search_author);
    if(entries == 0)
        cout << "There is no enty for this author. " << endl;
    else {
        for(sz_type i = 0; i != entries; ++i, ++iter)
            cout << iter->second << " ";
        cout << endl;
        cout << "This entry will be deleted!" << endl;
        sz_type n = 0;
        if(n = links.erase(search_author))
            cout << "delete " << n << " about the author successfully!" << endl;
        else
            cout << " delete error!";
    }

    //search multimap by iterator using equal_range
    cout << "Input another author: ";
    cin >> search_author;
    pair<multi_iter, multi_iter> pos = links.equal_range(search_author);
    if(pos.first != pos.second){
        while(pos.first != pos.second){
            cout << pos.first->second << " ";
            ++pos.first;
        }
        cout << endl;
        cout << "the entry will be deleted!" << endl;
        pair<multi_iter, multi_iter> pos = links.equal_range(search_author);
        links.erase(pos.first, pos.second);
        if(!links.count(search_author))
            cout << "delete successfully!" << endl;
        else 
            cout << "error!" << endl;
    }
    else
        cout << "There is no entry!" << endl;

    //order the entries by first order
    //use map to store the author name and count the entry numbers
    // map order the iterm by character automatically
    map<string, int> author_cnt;
    //get author name from multimap and cout
    for(multi_iter it = links.begin(); it != links.end(); ++it)
        ++author_cnt[it->first];
    //put put authors
    cout << "the authors and their entry numbers:" << endl;
    for(map<string, int>::iterator it = author_cnt.begin(); it != author_cnt.end(); ++it)
        cout << it->first << " " << it->second << endl;

    cout << "order authors by first character:" << endl;
    for(char c = 'A'; c != 'Z' + 1; ++c){
        cout << "Authors' names begin with '" << c << "': " << endl;
        for(map<string, int>::iterator it = author_cnt.begin(); it != author_cnt.end(); ++it){
            string au = it->first;
            if(*au.begin() == c){
                cout << au << " : ";
                multi_iter iter = links.find(au);
                for(sz_type cnt = 0; cnt != it->second; ++cnt, ++iter)
                    cout << iter->second << " ";
                cout << endl;
            }
        }   
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值