C++ Primer学习之(10)——关联容器
来源:互联网 发布:keep软件 编辑:程序博客网 时间:2024/04/30 16:39
P466:
关联容器通过键(key)存储和读取元素,而顺序容器则通过元素在容器中的位置顺序存储和访问元素。
map的元素以键-值对的形式组织;
set仅包含一个键,并且有效地支持关于某个键是否存在的查询。
pair,该类型在utility头文件中定义。
pair类型的使用相当繁琐,因此,如果需要定义多个相同的pair类型对象,可以考虑利用typedef简化其声明:
typedef pair<string, string> Author;Author proust("Marcel", "Proust");Author joyce("James", "Joyce");除了构造函数,标准库还定义了一个make_pair函数,由传递给它的两个实参生成一个新的pair对象。
pair<string, string> next_auth;string first, last;// generate a pair from first and lastnext_auth = make_pair(first, last);此操作等价于:
// use pair constructor to make first and last into a pairnext_auth = pair<string, string>(first, last);注:之前读代码读到一切关于pair和make_pair的代码都觉得头大,读完这段了然。
P470:
map类型通常可理解为关联数组(associative array):可是用键作为下标来获取一个值,正如内置数组类型一样。而关联的本质在于元素的值与某个特定的键相关联,而并非通过元素在数组中的位置来获取。
// count number of times each word occurs in the inputmap<string, int> word_count; // empty map from string to int在学习map接口时,需谨记value_type是pair类型,它的值成员可以修改,但键成员是 const类型不能修改。
对迭代器进行解引用,将获得一个引用,指向容器中一个value_type类型的值。对于map容器,其value_type是pair类型:
// *map_it is a reference to a pair<const string, int> objectcout << map_it->first; // prints the key for this elementcout << " " << map_it->second; // prints the value of the elementmap_it->first = "new key"; // error: key is const++map_it->second; // ok: we can change value through an iteratormap类额外定义了两种类型:key_type和mapped_type,以获取键和值得类型。
P474:
使用下标访问map与使用下标访问数组或vector的行为截然不同:用下标访问不存在的元素将导致在map容器中添加一个新元素,它的键即为该下标值。
map<string, int> word_count; // empty map// insert default initialized element with key Anna; then assign 1 to its valueword_count["Anna"] = 1;map迭代器返回value_type类型的值——包含const key_type和mapped_type类型成员的pair对象;下标操作符则返回一个mapped_type类型的值。
对于map容器,如果下标所表示的键在容器中不存在,则添加新元素,这一特性可使程序惊人地简练:
// count number of times each word occurs in the inputmap<string, int> word_count; // empty map from string to intstring word;while (cin >> word)++word_count[word];注:面试里经常会出现的统计问题,如果下次再碰到了,一定试试用map来解。
P477:
直接使用insert成员插入元素:
// if Anna not already in word_count, inserts new elements with value 1word_count.insert(map<string, int>::value_type("Anna", 1));传递给insert的实参相当笨拙,可使用两种方法简化:使用make_pair:
word_count.insert(make_pair("Anna"), 1);或使用typedef:
typedef map<string, int>::value_type valType;word_count.insert(valType("Anna", 1));带有一个键-值pair形参的insert版本将返回一个值:包含一个迭代器和一个bool值得pair对象,其中迭代器指向map中具有相应键的元素,而bool值则表示是否插入了该元素。
下面是使用insert重写的单词统计程序:
// count number of times each word occurs in the inputmap<string, int> word_count; // empty map from string to intstring word;while (cin >> word){// inserts element with key equal to word and value 1;// if word already in word_count, insert does nothingpair<map<string, int>::iterator, bool> ret = word_count.insert(make_pair(word, 1));if (!ret.second) // word already in word_count{++ret.first->second; // increment counter}}
P479:
下标操作符给出了读取一个值最简单的方法:
map<string, int> word_count;int occurs = word_count["foobar"];但是下标存在一个很危险的副作用:如果该键不在map容器中,那么下标操作会插入一个具有改键的新元素。
map容器提供了两个操作:count和find,用于检查某个键是否存在而不会插入该键。
m.count(k):返回m中k的出现次数。对于map对象,count成员的返回值只能是0或1。
m.find(k):如果m容器中存在按k索引的元素,则返回该元素的迭代器。如果不存在,则返回超出末端迭代器。
P482:
map对象的迭代编译
// get iterator positioned on the first elementmap<string, int>::const_iterator map_it = word_count.begin();// for each element in the mapwhile (map_it != word_count.end()){// print the element key, value pairscout << map_it->first << " occurs"<< map_it->second << " times" << endl;++map_it; // increment iterator to denote the next element}
set容器只是单纯地键的集合。在set容器中,value_type不是pair类型,而是与key_type相同的类型。set容器中的每个键都只能对应一个元素。
// define a vector with 20 elements, holding two copied of each number from 0 to 9vector<int> ivec;for (vector<int>::size_type i = 0; i != 10; ++i){ivec.push_back(i);ivec.push_back(i); // duplicate copies of each number}// iset holds unique elements from ivecset<int> iset(ivec.begin(), ivec.end());cout << ivec.size() << endl; // prints 20cout << iset.size() << endl; // prints 10
P490:
在multimap和multiset中查找元素
multiset和multimap类型允许一个键对应多个实例。例如,在电话簿中,每个人可能有单独的电话号码列表。在作者的文章集中,每位作者可能有单独的文章标题列表。
在multimap中,同一个键所关联的元素必然相邻存放。
有三种策略:
1. 使用find和count操作
首先,调用count确定某作者所写的书籍数目,然后调用find获得指向第一个该键所关联的元素的迭代器。for循环迭代的次数依赖于count返回的值。
2. 另一个更优雅简洁的方法是使用两个未曾见过的关联容器的操作:lower_bound和upper_bound。
lower_bound:返回的迭代器指向该键关联的第一个实例
upper_bound:返回的迭代器指向最后一个实例的下一个位置
// beg and end denote range of elements for this ahuthortypedef multimap<string, string>::iterator authors_it;authors_it beg = authors.lower_bound(search_item),end = authors.upper_bound(search_item);// loop through the number of entries there are for this authorwhile (beg != end){cout << beg->second << endl; // print each title++beg;}3. 更直接的方法是:调用equal_range函数来取代调用upper_bound和lower_bound函数。
equal_range函数返回存储一对迭代器的pair对象。如果该值存在,则pair对象的第一个迭代器指向该键关联的第一个实例,第二个迭代器指向该键关联的最后一个实例的下一位置。如果找不着匹配的元素,则pair对象中两个迭代器都将指向此键应该插入的位置。
// pos holds iterators that denote range of elements for this keypair<authors_it, authors_it> pos = authors.equal_range(search_item);// loop through the number of entries there are for this authorwhile (pos.first != pos.second){cout << pos.first->second << endl; // print each title++pos.first;}
最后给出的"容器综合应用:文本查询程序"可以好好读读,自己尝试写写。
容器一直是我很薄弱的地方,在工作中很少能想到用关联容器来存储数据,即使有些数据的关系很符合关联容器的模式。读完这章发现关联容器也没有那么麻烦那么难,在以后的工作中可以尝试多多使用。
第十章 关联容器(完)
- C++ Primer学习之(10)——关联容器
- C++Primer学习笔记(10)关联容器
- c++primer阅读笔记之关联容器学习
- C++ Primer学习笔记——$10 关联容器
- C++ Primer学习笔记——$10 关联容器
- C++Primer学习笔记第十章(10/18)关联容器
- 【C++primer学习笔记】第10章 关联容器
- C++primer学习:关联容器(1)
- C++primer学习:关联容器(2)
- C++primer学习:关联容器(3)
- C++primer学习:关联容器练习(4)
- C++primer 关联容器
- 《C++primer》关联容器
- 《C++Primer》读书笔记——第11章 关联容器
- c++Primer笔记(十 关联容器)
- c++primer(十)关联容器
- 《C++ Primer》学习笔记——关联容器
- C++ Primer 学习笔记——关联容器初识
- 黑马程序员_Java基础_集合框架
- 黑马程序员--编程基础I--
- 在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误。未找到或无法访问服务器。请验证实例名称是否正确并且 SQL Server 已配置为允许远程连接。
- 查看终端设备
- 数据库相关整理
- C++ Primer学习之(10)——关联容器
- Java中的简单工厂模式
- BT雷人的程序语言
- HotSpot VM GC 的种类
- ubuntu环境下重新编译内核
- Qt编程3--IP地址、MAC地址输入框
- Log4j输出到多个自定义文件 Log4j输出到多个自定义文件
- SSAO实现
- 如何编写一个CocoaPods的spec文件