zoukankan      html  css  js  c++  java
  • Associative Containers

    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;
    
  • 相关阅读:
    wxGlade: a GUI builder for wxWidgets/wxPython
    wxPython or PyQt or PySide哪一个比较好
    wxpython学习笔记
    C++实现发送HTTP请求 CoderZh 博客园
    Lucene如何分布式(WWW与Lucene服务器分离)
    MVC中一个表单实现多个提交按钮(一个action搞定添删改)
    何为.Net Remoting
    Lucene实用的分词匹配
    我心中的核心组件(可插拔的AOP)~第十四回 全文检索架构~终于设计了一个自己满意的Lucene架构
    【学习opencv第五篇】霍夫线变换
  • 原文地址:https://www.cnblogs.com/kid551/p/4267291.html
Copyright © 2011-2022 走看看