• STL map and multimap


    A Brief Introduction

    The map and multimap are key-value pair containers that allow for a lookup on the basis of a key. The difference between the map and multimap is that only the latter allows for duplicates, whereas the former can  store only unique keys.

    Th facilitate quick searching, STL implementations of the map and multimap internally look like a binary tree. This means that elements inserted in a map or a multimap are sorted on insertion. It also means that, unlike a vector where elements at a position can be replaced by another, elements in a map at a givens position cannot be replaced by a new element of a different value. This is because the map would ideally like to have it placed in a possible different location in accordance with its value relative to those in the internal tree.

    Basic STL map and multimap Operations


    Instantiating a std::map Object

    The template instantiation of the map class needs the programmer to specify the key type, the value type, and optionally a predicate that helps the map class to sort the elements on insertion.

    View Code
    #include <map>
    #include
    <string>

    int main()
    {
    using namespace std;

    map
    <int, string> mapIntegersToString;
    multimap
    <int, string> mmapIntegersToString;
    }

      

    Inserting Elements in an STL map or multimap

    View Code
    #include <map>
    #include
    <iostream>

    using namespace std;

    // Type-define the map and multimap definition for easy readability
    typedef map <int, string> MAP_INT_STRING;
    typedef multimap
    <int, string> MMAP_INT_STRING;

    int main ()
    {
    MAP_INT_STRING mapIntToString;

    // Insert key-value pairs into the map using value_type
    mapIntToString.insert (MAP_INT_STRING::value_type (3, "Three"));

    // Insert a pair using function make_pair
    mapIntToString.insert (make_pair (-1, "Minus One"));

    // Insert a pair object directly
    mapIntToString.insert (pair <int, string> (1000, "One Thousand"));

    // Insert using an array-like syntax for inserting key-value pairs
    mapIntToString [1000000] = "One Million";

    cout
    << "The map contains " << mapIntToString.size ();
    cout
    << " key-value pairs. " << endl;
    cout
    << "The elements in the map are: " << endl;

    // Print the contents of the map to the screen
    MAP_INT_STRING::const_iterator iMapPairLocator;

    for ( iMapPairLocator = mapIntToString.begin ()
    ; iMapPairLocator
    != mapIntToString.end ()
    ;
    ++ iMapPairLocator )
    {
    cout
    << "Key: " << iMapPairLocator->first;
    cout
    << " Value: " << iMapPairLocator->second.c_str ();

    cout
    << endl;
    }

    MMAP_INT_STRING mmapIntToString;

    // The insert function works the same way for multimap too
    mmapIntToString.insert (MMAP_INT_STRING::value_type (3, "Three"));
    mmapIntToString.insert (MMAP_INT_STRING::value_type (
    45, "Forty Five"));
    mmapIntToString.insert (make_pair (
    -1, "Minus One"));
    mmapIntToString.insert (pair
    <int, string> (1000, "One Thousand"));

    // A multimap can store duplicates - insert one
    mmapIntToString.insert (MMAP_INT_STRING::value_type (1000, "Thousand"));

    cout
    << endl << "The multimap contains " << mmapIntToString.size ();
    cout
    << " key-value pairs." << endl;
    cout
    << "The elements in the multimap are: " << endl;

    // Print the contents of the map to the screen
    MMAP_INT_STRING::const_iterator iMultiMapPairLocator;

    for ( iMultiMapPairLocator = mmapIntToString.begin ()
    ; iMultiMapPairLocator
    != mmapIntToString.end ()
    ;
    ++ iMultiMapPairLocator )
    {
    cout
    << "Key: " << iMultiMapPairLocator->first;
    cout
    << " Value: " << iMultiMapPairLocator->second.c_str ();

    cout
    << endl;
    }

    cout
    << endl;

    // The multimap can also return the number of pairs with the same key
    cout << "The number of pairs in the multimap with 1000 as their key: "
    << mmapIntToString.count (1000) << endl;

    return 0;
    }

    Output:

      The map contains 4 key-value pairs.

      The elements in the map are:

      Key: -1 Value: Minus One

      Key: 3 Value: Three

      Key: 1000 Value: One Thousand

      Key: 1000000 Value: One Million

      The multimap contains 5 key-value pairs.

      The elements in the multimap are:

      Key: -1 Value: Minus One

      Key: 3 Value: Three

      Key: 45 Value: Forty Five

      Key: 1000 Value: One Thousand

      Key: 1000 Value: One Thousand

      The number of pairs in the multimap with 1000 as their key are: 2

    Finding Elements in an STL map or multimap

    View Code
    #include <map>
    #include
    <iostream>
    #include
    <string>

    using namespace std;

    // Typedef the multimap definition for easy readability
    typedef multimap <int, string> MMAP_INT_STRING;

    int main ()
    {
    MMAP_INT_STRING mmapIntToString;

    // The insert function works the same way for multimap too
    mmapIntToString.insert (MMAP_INT_STRING::value_type (3, "Three"));
    mmapIntToString.insert (MMAP_INT_STRING::value_type (
    45, "Forty Five"));
    mmapIntToString.insert (MMAP_INT_STRING::value_type (
    -1, "Minus One"));
    mmapIntToString.insert (MMAP_INT_STRING::value_type (
    1000, "Thousand"));

    // A multimap can store duplicates - insert one
    mmapIntToString.insert (MMAP_INT_STRING::value_type
    (
    1000, "Thousand (duplicate)"));

    cout
    << "The multimap contains " << mmapIntToString.size ();
    cout
    << " key-value pairs." << endl;
    cout
    << "The elements in the multimap are: " << endl;

    // Print the contents of the map to the screen
    MMAP_INT_STRING::const_iterator iMultiMapPairLocator;

    for ( iMultiMapPairLocator = mmapIntToString.begin ()
    ; iMultiMapPairLocator
    != mmapIntToString.end ()
    ;
    ++ iMultiMapPairLocator )
    {
    cout
    << "Key: " << iMultiMapPairLocator->first;
    cout
    << ", Value: " << iMultiMapPairLocator->second << endl;
    }

    cout
    << endl;

    cout
    << "Finding all key-value pairs with 1000 as their key: " << endl;

    // Find an element in the multimap using the 'find' function
    MMAP_INT_STRING::const_iterator iElementFound;

    iElementFound
    = mmapIntToString.find (1000);

    // Check if "find" succeeded
    if (iElementFound != mmapIntToString.end ())
    {
    // Find the number of pairs that have the same supplied key
    size_t nNumPairsInMap = mmapIntToString.count (1000);
    cout
    << "The number of pairs in the multimap with 1000 as key: ";
    cout
    << nNumPairsInMap << endl;

    // Output those values to the screen
    cout << "The values corresponding to the key 1000 are: " << endl;
    for ( size_t nValuesCounter = 0
    ; nValuesCounter
    < nNumPairsInMap
    ;
    ++ nValuesCounter )
    {
    cout
    << "Key: " << iElementFound->first;
    cout
    << ", Value [" << nValuesCounter << "] = ";
    cout
    << iElementFound->second << endl;

    ++ iElementFound;
    }
    }
    else
    cout
    << "Element not found in the multimap";

    return 0;
    }

    Output:

      The multimap contains 5 key-value pairs.

      The elements in the multimap are:

      Key: -1, Value: Minus One

      Key: 3, Value: Three

      Key: 45, Value: Forty Five

      Key: 1000, Value: Thousand

      Key: 1000, Value: Thousand (duplicate)

      Finding all pairs with 1000 as their key...

      The number of pairs in the multimap with 1000 as key: 2

      The values corresponding to the key 1000 are:

      Key: 1000, Value [0] = Thousand

      Key: 1000, Value [1] = Thousand (duplicate)

    Erasing Elements from an STL map or multimap

    The erase function is invoked with the key as the parameter to delete all pairs with a certain key:

    mapObject.erase (key);

    Another form of the erase function allows the deletion of a particular element given an iterator that points to it:

    mapObject.erase (iElement);

    You can erase a range of elements from a map or a multimap using iterators that supply the bounds:

    mapObject.erase (iLowerBound, iUpperBound);

    View Code
    #include <map>
    #include
    <iostream>
    #include
    <string>

    using namespace std;

    // typedef the multimap definition for easy readability
    typedef multimap <int, string> MULTIMAP_INT_STRING;

    int main ()
    {
    MULTIMAP_INT_STRING mmapIntToString;

    // Insert key-value pairs into the multimap
    mmapIntToString.insert (MULTIMAP_INT_STRING::value_type (3, "Three"));
    mmapIntToString.insert (MULTIMAP_INT_STRING::value_type(
    45, "Forty Five"));
    mmapIntToString.insert (MULTIMAP_INT_STRING::value_type (
    -1, "Minus One"));
    mmapIntToString.insert (MULTIMAP_INT_STRING::value_type (
    1000, "Thousand"));

    // Insert duplicates into the multimap
    mmapIntToString.insert (MULTIMAP_INT_STRING::value_type (-1, "Minus One"));
    mmapIntToString.insert (MULTIMAP_INT_STRING::value_type (
    1000, "Thousand"));

    cout
    << "The multimap contains " << mmapIntToString.size ();
    cout
    << " key-value pairs. " << "They are: " << endl;

    // Print the contents of the multimap to the screen
    MULTIMAP_INT_STRING::const_iterator iPairLocator;

    for ( iPairLocator = mmapIntToString.begin ()
    ; iPairLocator
    != mmapIntToString.end ()
    ;
    ++ iPairLocator )
    {
    cout
    << "Key: " << iPairLocator->first;
    cout
    << ", Value: " << iPairLocator->second.c_str () << endl;
    }

    cout
    << endl;

    // Eraseing an element with key as -1 from the multimap
    if (mmapIntToString.erase (-1) > 0)
    cout
    << "Erased all pairs with -1 as key." << endl;

    // Erase an element given an iterator from the multimap
    MULTIMAP_INT_STRING::iterator iElementLocator = mmapIntToString.find(45);
    if (iElementLocator != mmapIntToString.end ())
    {
    mmapIntToString.erase (iElementLocator);
    cout
    << "Erased a pair with 45 as key using an iterator" << endl;
    }

    // Erase a range from the multimap...
    cout << "Erasing the range of pairs with 1000 as key." << endl;
    mmapIntToString.erase ( mmapIntToString.lower_bound (
    1000)
    , mmapIntToString.upper_bound (
    1000) );

    cout
    << endl;
    cout
    << "The multimap now contains " << mmapIntToString.size ();
    cout
    << " key-value pair(s)." << "They are: " << endl;

    // Print the contents of the multimap to the screen
    for ( iPairLocator = mmapIntToString.begin ()
    ; iPairLocator
    != mmapIntToString.end ()
    ;
    ++ iPairLocator )
    {
    cout
    << "Key: " << iPairLocator->first;
    cout
    << ", Value: " << iPairLocator->second.c_str () << endl;
    }

    return 0;
    }

    Output:

      The multimap contains 6 key-value pairs. They are:

      Key: -1, Value: Minus One

      Key: -1, Value: Minus One

      Key: 3, Value: Three

      Key: 45, Value: Forty Five

      Key: 1000, Value: Thousand

      Key: 1000, Value: Thousand

      Erased all pairs with -1 as key.

      Erased a pair with 45 as key using an iterator

      Erasing the range of pairs with 1000 as key.

      The multimap now contains 1 key-value pair(s).They are:

      Key: 3, Value: Three

    Supplying a Custom Sort Predicate

    The map and multimap template definition includes a third parameter that accepts the sort predicate for the map to function correctly. This third parameter, when not mentioned (as in the preceding examples), is substituted with the default sort criterion provided by std::less <>, which essentially compares two objects using the < operator.

    View Code
    #include <map>
    #include
    <algorithm>
    #include
    <string>
    #include
    <iostream>

    using namespace std;

    /*
    This is the binary predicate that helps the map sort
    string-keys irrespective of their case
    */
    struct CCaseInsensitive
    {
    bool operator () (const string& str1, const string& str2) const
    {
    string str1NoCase (str1), str2NoCase (str2);
    transform (str1.begin(), str1.end(), str1NoCase.begin(), tolower);
    transform (str2.begin(), str2.end(), str2NoCase.begin(), tolower);

    return (str1NoCase < str2NoCase);
    };
    };


    // Typedef map definitions for easy readability...
    // A directory that sorts keys using string::operator < (case sensitive)
    typedef map <string, string> DIRECTORY_WITHCASE;

    // A case-insensitive directory definition
    typedef map <string, string, CCaseInsensitive> DIRECTORY_NOCASE;

    int main ()
    {
    // Case-insensitive directory: case of the string-key plays no role
    DIRECTORY_NOCASE dirNoCase;

    dirNoCase.insert (DIRECTORY_NOCASE::value_type (
    "John", "2345764"));
    dirNoCase.insert (DIRECTORY_NOCASE::value_type (
    "JOHN", "2345764"));
    dirNoCase.insert (DIRECTORY_NOCASE::value_type (
    "Sara", "42367236"));
    dirNoCase.insert (DIRECTORY_NOCASE::value_type (
    "Jack", "32435348"));

    cout
    << "Displaying contents of the case-insensitive map:" << endl;

    // Print the contents of the map to the screen
    DIRECTORY_NOCASE::const_iterator iPairLocator1;
    for ( iPairLocator1 = dirNoCase.begin()
    ; iPairLocator1
    != dirNoCase.end()
    ;
    ++ iPairLocator1 )
    {
    cout
    << "Name: " << iPairLocator1->first;
    cout
    << ", Phone number: " << iPairLocator1->second << endl;
    }

    cout
    << endl;

    // Case-sensitive directory: case of the string-key affects
    // insertion & search
    DIRECTORY_WITHCASE dirWithCase;

    // Take sample values from previous map...
    dirWithCase.insert ( dirNoCase.begin(), dirNoCase.end() );

    cout
    << "Displaying contents of the case-sensitive map:" << endl;

    // Print the contents of the map to the screen
    DIRECTORY_WITHCASE::const_iterator iPairLocator2;
    for ( iPairLocator2 = dirWithCase.begin()
    ; iPairLocator2
    != dirWithCase.end()
    ;
    ++ iPairLocator2 )
    {
    cout
    << "Name: " << iPairLocator2->first;
    cout
    << ", Phone number: " << iPairLocator2->second << endl;
    }

    cout
    << endl;

    // Search for a name in the two maps and display result
    cout << "Please enter a name to search: " << endl << "> ";
    string strNameInput;
    cin
    >> strNameInput;

    DIRECTORY_NOCASE::const_iterator iSearchResult1;

    // find in the map...
    iSearchResult1 = dirNoCase.find (strNameInput);
    if (iSearchResult1 != dirNoCase.end())
    {
    cout
    <<iSearchResult1->first<< "'s number in the case-insensitive";
    cout
    << " directory is: " << iSearchResult1->second << endl;
    }
    else
    {
    cout
    << strNameInput << "'s number not found ";
    cout
    << "in the case-insensitive directory" << endl;
    }

    DIRECTORY_WITHCASE::const_iterator iSearchResult2;

    // find in the case-sensitive map...
    iSearchResult2 = dirWithCase.find (strNameInput);
    if (iSearchResult2 != dirWithCase.end())
    {
    cout
    << iSearchResult2->first<< "'s number in the case-sensitive";
    cout
    << " directory is: " << iSearchResult2->second << endl;
    }
    else
    {
    cout
    << strNameInput << "'s number was not found ";
    cout
    << "in the case-sensitive directory" << endl;
    }

    return 0;
    }

    Output:

      Displaying the contents of the case-insensitive map on the screen...

      Name: Jack, Phone number: 32435348

      Name: John, Phone number: 2345764

      Name: Sara, Phone number: 42367236

      Displaying the contents of the case-sensitive map on the screen...

      Name: Jack, Phone number: 32435348

      Name: John, Phone number: 2345764

      Name: Sara, Phone number: 42367236

      Please enter a name to search in the directories:

      > JOHN

      John’s number from the case-insensitive directory is: 2345764



  • 相关阅读:
    7 重排序与happens-before
    6 Java内存模型基础知识
    5 Java线程间的通信
    Java线程的状态及主要转化方法
    《The Boost C++ Libraries》 第一章 智能指针
    python通过swig调用静态库
    使用gdb调试
    Rsync服务部署使用
    UNP学习总结(二)
    read()函数的困惑
  • 原文地址:https://www.cnblogs.com/DanielZheng/p/2135781.html
Copyright © 2020-2023  润新知