Notes from C++ Primer

Associative containers differ in fundamental respect from the sequential containers: elements in associative containers are stored and retrieved by a key, in contrast to elements in a sequential container, which are stored and accessed sequentially by their position within the container.

Associative container supports using key to find and access element with high efficiency. There're two base associative container type: map and set. The element of map is organized with the key-value form: the key is used as the index of map, and the value is the data of storing and accessing. The set contains only one key and supports efficient queries to whether a given key is present.

pair Type

pair is also a kind of template type, but with two type parameters passing when pair is initialized.

pair<string, string> anon;			// holds two strings
pair<string, int> word_count; // holds a string and an int
pair<string, vector<int> > line; // holds string and vector<int>

We also can provides initial value in definition:

pair<string, string> author("James", "Joyce");

If we need to define many same pair type, we can use typedef to simplify the declaration:

typedef pair<string, string> Author;
Author proust("Marcel", "Proust");
Author joyce("James", "Joyce");

pair object has two member variable: first, and second. The dot operation can be used to access them:

string firstBook;

// access and test the data members of the pair
if(author.first == "James" && author.second == "Joyce")
firstBook = "Stephen Hero";

The library provides make_pair function to generate new pair object:

pair<string, string> next_auth;
string first, last;
while(cin >> first >> last)
{
// generate a pair from first and last
next_auth = make_pair(first, last); // process next_auth ...
}

These operations are equivalent to the below operations:

// use pair constructor to make first and last into a pair
next_auth = pair<string, string>(first, last);

or read directly from input stream:

pair<string, string> next_auth;

// read directly into the members of next_auth
while(cin >> next_auth.first >> next_auth.second)
{
// process next_auth ...
}

map Type

A map is a collection of key-value pairs. It is often referred as an associative array: use the key to get value instead of using position to get value. There's a constraint for the key type. The type of key must support the comparasion function "<". And the "<" relationship must be validate.

Dereference the map iterator will generate pair type object:

// count number of times each word occurs in the input
map<string, int> word_count; // empty map from string to int // get an iterator to an element in word_count
map<string, int>::iterator map_it = word_count.begin(); // *map_it is a reference to a pair<const string, int> object
cout << map_it->first; // prints the key for this element
cout << map_it->second; // prints the value of the element
map_it->first = "new key"; // error: key is const
++map_it->second; // ok: we can change value through an iterator

Add elements for map

Add elements for map can be operated by using functino insert, or using subscript operation to fetch element and then assigning value.

map<string, int> word_count;	// empty map

// insert default initialized element with key Anna; then assign 1 to its value
word_count["Anna"] = 1;

These codes are equivalent to:

  1. Find the element with key "Anna". Failed.
  2. Create a new key-value pairs for inserting into word_count. Its key is const string type object storing Anna. Its value is initialized by default constructor or just value 0.
  3. Insert the new key-value pairs.
  4. Fetch the element inserted just now, and assign its value as 1.

The behaviors of using subscript accessing map and accessing vector are totally different. Using subscript access inexistent element in map will lead to adding a new element in map. Its subscript will be the key.

The return type of subscript operation is mapped value type, and the return type of map iterator is const key_type and mapped_type pair object.

cout << word_count["Anna"];		// fetch element indexed by Anna; prints 1
++word_count["Anna"]; // fetch the element and add one to it
cout << word_count["Anna"]; // fetch the element and print it; prints 2

The behavior of adding new element when accessing inexistent value's key will simplify program:

// count number of times each word occurs in the input
map<string, int> word_count; // empty map from string to int
string word;
while(cin >> word)
++word_count[word];

use of map::insert

Use map::insert instead of subscript operation to add new element:

// if Anna not already in word_count, inserts new element with value 1
word_count.insert(map<string, int>::value_type("Anna", 1));

map::insert can avoid the unnecessary initialization in subscription operation. A more concise way:

word_count.insert(make_pair("Anna", 1));

or use typedef

typedef map<string, int>::value_type valType;
word_count.insert(valType("Anna", 1));

If the key of inserting element is existing, the insert won't do any operations. The one key-value pairs formal parameter version insert will return a pair object including one iterator and one bool value. The iterator points to the element in map with corresponding key. If the bool is false, it means the key of inserting element is existing in map, keep the key without changing; If the bool is true, add one new element.

// count number of times each word occurs in the input
map<string, int> word_count; // empty map from string to int
string word;
while(cin >> word)
{
// insert element with key equal to word and value 1
// if word already in word_count, insert does nothing
pair<map<string, int>::iterator, bool> ret = word_count.insert(make_pair(word, 1)); if(!ret.second)
++ret.first->second; // increment counter
}

Find and retrieve element in map

The easiest way to retrieve a value is to use subscript operation:

map<string, int> word_count;
int occurs = word_count["foobar"];

But the subscript operation has important side effect: if the key is not existing in map, then subscript operation will insert a new element with the key and default initial value. So, if the "foobar" is not existing, then pairs with key: foobar and value: 0 will be inserted into map: word_count. And the occurs will get 0.

So map container provides two operations: count and find to check if a key is existing without inserting a new element with the key.

  • m.count(k)    return the times of k in m
  • m.find(k)       if exist the element with key k, return the iterator of that element, else return the off-the-end iterator

For the map object, the return value of count is 0 or 1. The return value of multimap container is more useful. Thus if the return value of count is not 0, we can use subscript operation to access the value avoiding adding new element:

int occurs = 0;
if(word_count.count("foobar"))
occurs = word_count["foobar"];

There, after the execution of count, the use of subscript operation will lead to one more search process. Thus there're two find processes in total. The use of find will only need one find process:

int occurs = 0;
map<string, int>::iterator it = word_count.find("foobar");
if(it != word_count.end())
occurs = it->second;

Associative Containers的更多相关文章

  1. 关联式容器(associative containers)

    关联式容器(associative containers) 根据数据在容器中的排列特性,容器可分为序列式(sequence)和关联式(associative)两种. 标准的STL关联式容器分为set( ...

  2. [c++] Associative Containers

    关联容器 和 顺序容器 的本质差别在于: 关联容器通过键(key)存储和读取元素,而顺序容器则通过元素在容器中的位置顺序存储和访问元素. Reference: http://www.cnblogs.c ...

  3. Understand the Qt containers(有对应表)

    Container classes are one of the cornerstones of object-oriented programming, invaluable tools that ...

  4. C++ std::set

    std::set template < class T, // set::key_type/value_type class Compare = less<T>, // set::k ...

  5. C++ std::multimap

    std::multimap template < class Key, // multimap::key_type class T, // multimap::mapped_type class ...

  6. C++ std::map

    std::map template < class Key, // map::key_type class T, // map::mapped_type class Compare = less ...

  7. C++ std::multiset

    std::multiset template < class T, // multiset::key_type/value_type class Compare = less<T>, ...

  8. C++ 关联容器

    <C++ Primer 4th>读书笔记 关联容器和顺序容器的本质差别在于:关联容器通过键(key)存储和读取元素,而顺序容器则通过元素在容器中的位置顺序存储和访问元素. 关联容器(Ass ...

  9. [Code::Blocks] Install wxWidgets & openCV

    The open source, cross platform, free C++ IDE. Code::Blocks is a free C++ IDE built to meet the most ...

随机推荐

  1. IDEA(MAC) 快捷键

    从eclipse到IDEA:从Windows到MAC 有些不习惯,记录一些日常使用的快捷键 1.格式化代码 command+alt+L 2.导包 alt+ enter 3.自动生成该类型的对象 com ...

  2. MySQL 8.0 新增SQL语法对窗口函数和CTE的支持

    尝试了一下MySQL 8.0的部分新特性. 如果用过MSSQL或者是Oracle中的窗口函数(Oracle中叫分析函数), 然后再使用MySQL 8.0之前的时候,就知道需要在使用窗口函数处理逻辑的痛 ...

  3. Ubuntu输入命令无效的问题

    https://blog.csdn.net/u014797226/article/details/80800550?utm_source=blogxgwz2 Ubuntu启动时输入密码后,一直停留在登 ...

  4. 使用rpm-build制作nginx的rpm包

    2014-11-27 11:05:49   一.RPM包的分类 RPM有五种基本的操作功能:安装.卸载.升级.查询和验证. linux软件包分为两大类: (1)二进制类包,包括rpm安装包(一般分为i ...

  5. CSS表单2 组件排版

    <!DOCTYPE html> <html>     <head>         <title>单选按钮对齐</title>        ...

  6. aptana怎么显示空格 tab和回车等

  7. cdnbest如何让用户访问走最近最快的线路(分组线路)

    用户访问网站有时网络有互通的问题,cdnbest的分组解析可以细分线路,让用户访问自动走最优线路,线路不细分都加默认里,访问的节点是随机分配的 下面我们讲下如何设置: 比如你有电信,移动,和国外的节点 ...

  8. 在网站中使用UEditor富文本编辑器

    UEditor是由百度WEB前端研发部开发的所见即所得的开源富文本编辑器,具有轻量.可定制.用户体验优秀等特点. 官网链接 进入到下载页面,选择相应的版本下载 这里我们使用ASP.NET开发,所以选择 ...

  9. java爬虫框架webmagic学习(一)

    1. 爬虫的分类:分布式和单机 分布式主要就是apache的nutch框架,java实现,依赖hadoop运行,学习难度高,一般只用来做搜索引擎开发. java单机的框架有:webmagic和webc ...

  10. 回忆Partition算法及利用Partition进行快排

    一.Partiton算法 Partiton算法的主要内容就是随机选出一个数,将这个数作为中间数,将大于它的排在它右边,小于的排在左边(无序的). int partition (int arr[],in ...