Introduction to the use of multimap in STL

In the article " Creating Associative Containers with the <map> Library ", we discussed the map associative container in the standard library. But that's only part of the map container. The standard library also defines a multimap container, which is similar to map except that it allows duplicate keys. This property makes multimap more useful than expected: for example, the same person in a phone book can have more than two phone numbers, a file system can map multiple symbolic links to the same physical file, or a DNS server can map several URLs map to the same IP address. In these cases, you can do something like this:
// Note: Pseudocode
            multimap <string, string> phonebook;
            phonebook.insert("Harry","8225687"); // home phone
            phonebook.insert("Harry","555123123"); // unit phone
            phonebook.insert("Harry"," 2532532532"); // mobile phone

  The ability to store duplicate keys in a multimap greatly affects its interface and usage. So how do you create associative containers with non-unique keys? The answer is to use the multimap container defined in the <map> library.

Ask questions
  Unlike maps, multimaps can contain duplicate keys. This raises a question: how does overloading the subscript operator return multiple associated values ​​for the same key? Take the following pseudocode as an example:

string phone=phonebook["Harry];

  The standard library designers' solution to this problem was to remove the subscript operator from the multimap. Therefore, different methods are needed for inserting and retrieving elements and for error handling.

Insert
   Suppose you need to develop a DNS daemon (that is, a service program in Windows) that maps IP addresses to matching URL strings. You know that in some cases the same IP address will be associated with multiple URLs. These URLs all point to the same site. In this case, you should use multimap, not map. E.g:

#include <map>
            #include <string>
            multimap <string, string> DNS_daemon;

  Use the insert() member function instead of the subscript operator to insert elements. insert() has a   parameter of type pair . In " Creating Associative Containers with the <map> Library " we demonstrated how to use the make_pair() helper function to accomplish this task. You can also use it like this:

DNS_daemon.insert(make_pair("213.108.96.7","cppzone.com"));

  In the insert() call above, the string "213.108.96.7" is the key and "cppzone.com" is its associated value. Later inserts are the same key, different associated value:

DNS_daemon.insert(make_pair("213.108.96.7","cppluspluszone.com"));

  Therefore, DNS_daemon contains two elements with the same key. Note that the values ​​returned by multimap::insert() and map::insert() are different.

typedef pair <const Key, T> value_type;
            iterator
            insert(const value_type&); // #1 multimap
            pair <iterator, bool>
            insert(const value_type&); // #2 map

   The multimap::insert() member function returns an iterable pointer to the newly inserted element, which is an iterator (multimap::insert() always succeeds). But map::insert() returns pair<iterator, bool>, where the bool value indicates whether the insertion operation was successful.

Finding a single value
  Like map, multimap has two overloaded versions of the find() member function:

iterator find(const key_type& k);
            const_iterator find(const key_type& k) const;

find(k) returns an iterable pointer to the first pair matching key k, that is, when you want to check if there is at least one value associated with that key, or just the first match, this functions are most useful. E.g:

typedef multimap <string, string> mmss;
            void func(const mmss & dns)
            {
            mmss::const_iterator cit=dns.find("213.108.96.7");
            if (cit != dns.end())
            cout <<"213.108.96.7 found" <<endl;
            else
            cout <<"not found" <<endl;
            }

Handling Multiple Associated Values
  ​​The count(k) member function returns the number of values ​​associated with a given key. The following example reports how many values ​​are associated with the key "213.108.96.7":

cout<<dns.count("213.108.96.7") //output: 2
            <<" elements associated"<<endl;

  To access multiple values ​​in a multimap, use the equal_range(), lower_bound(), and upper_bound() member functions:
equal_range(k): This function finds all values ​​associated with k. Returns a pair of iteration pointers that mark the beginning and end of the range. The following example displays all the values ​​associated with the key "213.108.96.7":

typedef multimap <string, string>::const_iterator CIT;
            typedef pair<CIT, CIT> Range;
            Range range=dns.equal_range("213.108.96.7");
            for(CIT i=range.first; i!=range.second; ++i)
            cout << i->second << endl; //output: cpluspluszone.com
            // cppzone.com

   lower_bound() 和 upper_bound():lower_bound(k) 查找第一个与键 k 关联的值,而 upper_bound(k) 是查找第一个键值比 k 大的元素。下面的例子示范用 upper_bound()来定位第一个其键值大于“213.108.96.7”的元素。通常,当键是一个字符串时,会有一个词典编纂比较:

dns.insert(make_pair("219.108.96.70", "pythonzone.com"));
            CIT cit=dns.upper_bound("213.108.96.7");
            if (cit!=dns.end()) //found anything?
            cout<<cit->second<<endl; //display: pythonzone.com

如果你想显示其后所有的值,可以用下面这样的循环:

// 插入有相同键的多个值
            dns.insert(make_pair("219.108.96.70","pythonzone.com"));
            dns.insert(make_pair("219.108.96.70","python-zone.com"));
            // 获得第一个值的迭代指针
            CIT cit=dns.upper_bound("213.108.96.7");
            // 输出: pythonzone.com,python-zone.com
            while(cit!=dns.end())
            {
               cout<<cit->second<<endl;
               ++cit;
            }
结论
  虽然 map 和 multimap 具有相同的接口,其重要差别在于重复键,设计和使用要区别对待。此外,还要注意每个容器里 insert()成员函数的细微差别。

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324779812&siteId=291194637