笔记:C++学习之旅---关联容器

笔记:C++学习之旅---关联容器

      关联容器和顺序容器有着根本的不同:关联容器中的元素是按关键字来保存和访问的。与之相对,顺序容器中的元素是按它们在容器中的位置来顺序保存和访问的
      关联容器支持高效的关键字查找和访问。两个主要的关联容器类是mapset
map中的元素是一些关键字的-值(key-value)对:关键字起到索引的作用,值则表示与索引相关联的数据。set中每个元素只包含一个关键字:set支持高效的关键字查询操作--检查一个给定关键字是否在set中。

例子:
一个经典的使用关联数组的例子是单词计数程序:
#include <iostream>
#include <string>
#include <map>
#include <set>
using namespace std;

int main()
{
             map < string , size_t > word_count;
             string word;
             set < string > exclude = { "The" , "But" , "And" , "Or" , "An" , "A" , "the" , "but" , "and" , "or" , "an" , "a" }; //忽略的单词
            cout << "请输入一串英文单词\n" ;
             while (cin >> word)
            {
                         if (word == "#" )
                                     break ;
                         if (exclude.find(word) == exclude.end())
                        {
                                    ++word_count[word];
                        }
            }
                         for ( const auto &w : word_count)
                        cout << w.first << " occurs " << w.second << ((w.second > 1) ? " times " : " time " ) << endl;

             return 0;
}
练习11.3 11.4:
编写你自己的单词计数程序,忽略大小写和标点。如,"example"“example,”和“Example”应该递增相同的计数器。

#include <iostream>
#include <map>
#include <string>
#include <algorithm>
using namespace std;

void print( map < string , size_t > & map )
{
             for ( auto &m : map)
                        cout <<m.first<< ":" <<m.second<<endl;
}
void word_count_pro( map < string , size_t > & m )
{
             string word;
            cout << "请输入一串英文单词\n" ;
             while (cin >> word)
            {
                         if (word == "#" )
                                     break ;
                         for ( auto &ch : word)
                                    ch = towlower(ch); //大小写转换;
                        word.erase(remove_if(word.begin(), word.end(), ispunct), word.end()); //ispunct 判断是否为标点符号或者特殊字符进行删除;
                        ++ m [word];
            }
            print( m );
}
int main()
{
             map < string , size_t > map;
            word_count_pro(map);
             return 0;
}

关联容器的概述

#include <iostream>
#include <vector>
#include <map>
#include <set>
using namespace std;

int main()
{
             vector < int > vec;
             for ( vector < int >:: size_type i = 0; i != 10; ++i)
            {
                        vec.push_back(i);
                        vec.push_back(i);
            }
             set < int > iset(vec.cbegin(), vec.cend());
             multiset < int > miset(vec.cbegin(), vec.cend());
            cout << vec.size() << endl; //20
            cout << iset.size() << endl; //10
            cout << miset.size() << endl; //20
             return 0;
}

练习11.7:
定义一个map,关键字是家庭的姓,值是一个vector,保存家中孩子(们)的名。编写代码,实现添加新的家庭以及向已有家庭中添加新的孩子。
#include <iostream>
#include <vector>
#include <string>
#include <map>
using namespace std;

void print( multimap < string , vector < string >> & family )
{
             //按照英文名称习惯打印名字,如Tom.Green
             for ( auto &member : famil y )
            {
                        cout << "Mumber is:" << " " << endl;
                         for ( auto it = member.second.begin(); it != member.second.end(); ++it)
                        {
                                    cout << *it << "." << member.first << endl;
                        }
                        cout << endl;
            }
}
int main()
{
             string fname = "" , name = "" ;
             vector < string > vec = { "Tom" , "Jerry" , "Lucy" };
             multimap < string , vector < string >> family = { { "Green" , vec }, { "white" , vec } };

            print(family); //打印结果

             //先输入family name,然后自己name
             //while (cin >> fname >> name)
             //family[fname].push_back(name);

             //修改地方,先输入名,再输入姓,可以重复保存了,所以不像上面那样来插入名字
            cout << "请输入你的名:\n" ;
             while (cin >> fname)
            {
                         vector < string > vec;
                        cout << "请输入你的性(输入end退出):\n" ;
                         while (cin >> name && name != "end" ) //以end结束输入
                        {
                                    vec.push_back(name);
                        }
                                    family.insert({fname,vec }); //将姓插入到名前面
                                     //添加新家庭后再次打印
                                    print(family);
            }      
             return 0;
}

pair类型
类似容器,pair是一个用来生成特定类型的模版。与其他标准库类型不同,pair的数据成员public的两个成员分别命名为first和second。

关联容器的操作

向map中添加元素
对于一个map进行insert操作时,必须记住元素类型是pair。

练习11.20:
重写单词计数程序,使用insert代替下标操作。你认为哪个程序更容易编写和阅读
#include <iostream>
#include <vector>
#include <map>
#include <string>
using namespace std;

int main()
{
             map < string , size_t > word_count;
             string word;
            cout << "请输入一串字符串\n" ;
             while (cin >> word)
            {
                         if (word == "#" )
                                     break ;
                         auto ret = word_count.insert({ word, 1 });//创建一个pair
                         if (!ret.second)
                        {
                                    ++ret.first->second;//map中值部分
                        }
            }
             for ( auto &w : word_count)
                        cout << w.first << " " << w.second << ((w.second > 1) ? " times " : " time " )<<endl;

             return 0;
}

删除元素

练习11.31:
编写程序,定义一个作者及其作品的multimap。使用find在multimap中查找一个元素并用erase删除它。确保你的程序在元素不在map中时也能正常运行。
#include <iostream>
#include <string>
#include <map>
#include <algorithm>
using namespace std;

int main()
{
             multimap < string , string > authors{ { "alan" , "DMA" }, { "pezy" , "LeetCode" }, { "alan" , "CLRS" },
            { "wang" , "FTP" }, { "pezy" , "CP5" }, { "wang" , "CPP-Concurrency" } };
            
            cout << "erase before:\n" ;
             for ( auto &a : authors)
                        cout << a.first << ":" <<a.second<< endl;

             string author = "pezy" ;
             string work = "CP5" ;

             auto found = authors.find(author); //找到作者;
             auto count = authors.count(author); //记录次数;
             while (count)
            {
                         if (found->second == work) //找到CP5,然后删除;
                        {
                                    authors.erase(found);
                                     break ;
                        }
                        ++found;
                        --count;
            }
            cout << "erase after:\n" ;
             for ( const auto & author : authors)
                        cout << author.first << ":" << author.second << std::endl;

             return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值