C++primer第五版笔记-第十一章关联容器

本文详细介绍了C++中关联容器的使用方法,包括map和set的基本操作、关键字类型的定义及要求、元素的添加与访问等。并通过实例展示了如何利用这些容器解决实际问题。

1、 使用关联容器

map类型通常被称为关联数组,不同之处就是其下标不必是整数。通过关键字而不是位置查找其值。set是关键字的简单集合。

使用map:

 //统计每个单词在输入中出现的次数
    map<string,size_t> word_count;//string到size_t的空map
    
    string word;
    
    while (cin>>word) {
        ++word_count[word]; //提取word计算器并加1
    }
    for(const auto &w:word_count)//对map中的每个元素
        //打印结果
        cout<<w.first<<"occurs"<<w.second<<((w.second>1)?"times":"time")<<endl;

使用set

    //统计每个单词在输入中出现的次数
    map<string,size_t> word_count;//string到size_t的空map
    
    set<string> exclude={"The","But","and","Or","An","A",
                         "the","but","and","or","an","a"};
    
    string word;
    
    while (cin>>word) {
        ++word_count[word]; //提取word计算器并加1
        
        //t统计不在exclude中的单词
        if(exclude.find(word)==exclude.end())
            ++word_count[word];//获取递增word的计数器
    }

初始化multimap和multiset

他们允许多个元素具有相同的关键字。

2、关联容器概述

定义一个map时,必须指明关键字类型又指明值类型,而定义一个set时候,只需要指明关键字类型

当初始化一个map时,必须提供关键字类型和值类型。我们将每个关键字和值包围在花括号中:{key,value}

    //定义一个又20个元素的vector,保存0-9每个整数的两个拷贝
    vector<int> ivec;
    for(vector<int>::size_type i = 0; i != 10;++i){
        ivec.push_back(i);
        ivec.push_back(i);//每个数重复保存一次
    }
    
    //iset包含来自ivec的不重复元素,miset包含所有20个元素
    set<int> iset(ivec.cbegin(),ivec.cend());
    multiset<int> miset(ivec.cbegin(),ivec.cend());
    
    cout<<ivec.size()<<endl;//打印20
    cout<<iset.size()<<endl;//打印10
    cout<<miset.size()<<endl;//打印20


关键字类型的要求

bool copareIsbn(const Sales_data &lhs,const Sales_data &rhs){
    return lhs.isbn()()<rhs.isbn();
}

//bookstore中多条记录可以有相同的ISBD
//bookstore中的元素可以以ISBN的顺序进行排列
multiset<Sales_data,decltype(compareIsbn)*> bookstore(compareIsbn);

pair类型

一个pair保存两个数据成员

    pair<string, string> anon;//保存两个string
    pair<string, size_t> word_count;//保存一个string和一个size_t
    pair<string,vector<int>> line;//保存string和vector<int>

pair数据成员是public的,这一点与其他容器不同



创建pair对象的函数

pair<string, int>
process(vector<string> &v){
    if(!v.empty())
        return {v.back(),v.back().size()};//列表初始化
    else
        return pair<string, int>();//隐式构造函数
}
若v不为空,我们返回一个由v中最后一个string及其大小组成的pair,否则返回一个空的pair。并返回它。

3、关联容器操作

key_type  此容器类型的关键字类型

mapped_type 每个关键字关联的类型,只适用map

value_type 对于set,与key_type相同

 对于map,为pair<const key_type,mapped_type>


    set<string>::value_type v1;//v1是一个string
    set<string>::key_type v2;//v2是一个string
    map<string,int>::value_type v3;//v3是一个pair<const string,int>
    map<string, int>::key_type v4;//v4是一个string
    map<string,int>::mapped_type v5;//v5是一个int

关联容器迭代器

    //获得指向word_count中一个元素的迭代器
    auto map_it = word_count.begin();
    //*map_it 是指向一个pair<const string,size_t>对象的引用
    cout <<map_it->first;//打印此元素的关键字
    cout << " "<<ap->second;//打印此元素的值
    map->it->first="new key";
    ++map_it->second;//正确,我们可以通过迭代器改变元素
    //set的迭代器是const
    set<int> iset ={0,1,2,3,4,5,6,7,8,9};
    set<int>::iterator set_it = iset.begin();
    if(set_it != iset.end()){
        *set_it = 42;//错误,set中关键字是只读的
        cout<<*set_it<<endl;//正确,可以读关键字
    }

遍历关联容器

    //获得一个指向首元素的迭代器
    auto map_it = word_count.cbegin();
    //比较当前迭代器和尾后迭代器
    while (map_it != word_count.cend()) {
        //解引用迭代器,打印关键字-值对
        cout<<map_it->first<<"occurs"
            <<map->second<<"times"<<endl;
        
        ++map_it;//递增迭代器,移动到下一个元素
    }

关联容器和算法:通常不对关联容器使用泛型算法,关键字是const这一特性意味着不能将关联容器传递给修改或者重排容器元素的算法。set类型中的元素是const,map中的元素是pair,其第一个成员是const。


添加元素

    vector<int> ivec ={2,4,6,8,2,4,6,8};//ivec又8个元素
    set<int> set2;//空集合
    set2.insert(ivec.cbegin(),ivec.cend());//set2有4个元素
    set2.insert({1,3,5,7,1,3,5,7});
    
    //向map添加元素
    //向word_count插入word的4种方法
    word_count.insert({word,1});
    word_count.insert(make_pair(word,1));
    word.count.insert(pair<string, size_t>(word,1));
    word.count.insert(map<string,size_t>::value_type(word,1));

    //统计每个单词在输入中出现的次数的一种比较繁琐的办法
    map<string,size_t> word_count;//从string到size_t的空map
    string word;
    while (cin>>word) {
        //插入一个元素,关键字等于word,值为1
        //若word已在word——cout中,insert什么也不做
        auto ret = word_count.insert({word,1});
        
        if(!ret.second)
            ++ret.first->second;
    }



map的下标操作

    map<string,size_t> word_count;
    //插入一个关键字“anna”,关联值进行初始化,然后将1赋予它
    word_count["anna"]=1

在word_count中搜索关键字为anna的元素,未找到

将一个新的关键字-值对插入到word_count中。关键字是一个const string。保存anna。值进行初始化。本例中为0

提取新插入的元素,并将它赋值为1

c[k]:返回关键字为k的元素,如果关键字k不在c中,添加一个关键字为k的元素,对其进行值初始化

c.at[k] 访问关键字为k的元素,带参数检查,若k不在c中,抛出异常



访问元素

    set<int> iset={0,1,2,3,4,5,6,7,8,9};
    iset.find(1);//返回一个迭代器
    iset.find(11);//返回一个迭代器,其值等于iset.cend()
    iset.count(1);//返回1
    iset.count(11);//返回0

c.lower_bound(k)  返回一个迭代器,指向一个关键字不小于k的元素

c.upper_bound(k)  返回一个迭代器,指向关键字大于k的、元素

c.equal_range(k) 返回一个迭代器pair,表示关键字等于k的元素的范围,若k不错,pair的两个成员军等于c.end()


在multimap和multyiset中查找元素

    string search_item("anna");
    auto entries = authors.count(search_item);
    auto iter = authors.find(search_item);//
    //用一个循环查找此作者的所有著作
    while (entries) {
        cout<<iter->second<<endl;//打印每个题目
        ++iter;//前进到下一个
        --entries;//记录已经打印了多少个
    }


一个单词转换的map

单词转换函数

void word_transform(ifstream &map_file,ifstream &input){
    auto trans_map=buildMap(map_file);//保存转换规则
    string text;//保存输入中的每一刚
    while(getline(input, text)){//读取输入中的一行到text
        istringstream stream(text);//读取诶个单词
        bool firstword=true;//控制是否打印空格
        while (stream>>word) {
            if(firstword)
                firstword = false;
            else
                cout<<" ";//在单词间打印一个空格
            //transform返回它的第一个参数或者其转换后的形式
            cout<<trasform(word,trans_map);//打印输出
            
        }
        cout<<endl;
        
    }
}

简历转换映射函数

map<string,string> buildMap(ifstream &map_file){
    map<string,string> trans_map;//保存转换规则
    string key;//要转换的单词
    string value;//替换后的内容
    //读取第一个单词存入key中,行中剩余内容存入value
    while (map_file>>key &&getline(map_file,value)) {
        if(value.size() >1){//检查是否有转换规则
            trans_map[key]= value.substr(1);//跳过前导空格
        }
        else
            throw runtime_error("no rule for "+key);
        
    }
    return trans_map;
}

生成转换文本

const string & transform(const string &s,const ap<string,string> &m){
    //实际的转换工作,此部分是程序的核心
    auto map_it = m.find(s);
    //如果单词在转换规则map中
    if(map_it != m.cend())
        return map_it->second; //使用替换短语
    else
        return s;
}



4、无序容器

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值