C++STL之map與multimap的使用

/*
map是STL的一個關聯容器,它提供一對一(其中第一個可以稱爲關鍵字,每個關鍵字只能在map中出現一次,
第二個可能稱爲該關鍵字的值)的數據處理能力,由於這個特性,它完成有可能在我們處理一對一數據的時候,
在編程上提供快速通道。這裏說下map內部數據的組織,map內部自建一顆紅黑樹(一種非嚴格意義上的平衡二叉樹),
這顆樹具有對數據自動排序的功能,所以在map內部所有的數據都是有序的,後邊我們會見識到有序的好處。
下面舉例說明什麼是一對一的數據映射。比如一個班級中,每個學生的學號跟他的姓名就存在着一一映射的關係,
這個模型用map可能輕易描述,很明顯學號用int描述,姓名用字符串描述(本篇文章中不用char *來描述字符串,
而是採用STL中string來描述), 下面給出map描述代碼:
[cpp] view plain copy
map<int, string> mapStudent;
*/
//1.map的構造函數
//map共提供了6個構造函數,這塊涉及到內存分配器這些東西,略過不表,在下面我們將接觸到一些map的構造方法,
//這裏要說下的就是,我們通常用如下方法構造一個map:
//[cpp] view plain copy
//map<int, string> mapStudent;
//2.數據的插入
//在構造map容器後,我們就可以往裏面插入數據了。這裏講三種插入數據的方法:
//第一種:用insert函數插入pair數據,下面舉例說明(以下代碼雖然是隨手寫的,
//應該可以在VC和GCC下編譯通過,大家可以運行下看什麼效果,在VC下請加入這條語句,
//屏蔽4786警告  #pragmawarning (disable:4786))
//[cpp] view plain copy

#include <map>  
#include <string>  
#include <iostream>  
using namespace std;
int main()
{
    map<int, string> mapStudent;//pair<int,string>p;p=make_pair(v1,v2);<span style="color: rgb(255, 0, 0);
    //background-color: rgb(240, 248, 255); font-family: Arial; font-size: 13px; "> </span>  
    mapStudent.insert(pair<int, string>(1, "student_one"));
    mapStudent.insert(pair<int, string>(2, "student_two"));
    mapStudent.insert(pair<int, string>(3, "student_three"));
    map<int, string>::iterator  iter;
    for (iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
    {
        cout << iter->first << "  " << iter->second << endl;
    }
}

//[cpp] view plain copy
//make_pair()//返回類型爲對應的pair類型  
//無需寫出類別,就可以生成一個pair對象
//例:
//make_pair(1, '@')
//而不必費力的寫成
//pair<int, char>(1, '@')
//第二種:用insert函數插入value_type數據,下面舉例說明
//[cpp] view plain copy
#include <map>  
#include <string>  
#include <iostream>  
using namespace std;
int main()
{
    map<int, string> mapStudent;
    mapStudent.insert(map<int, string>::value_type(1, "student_one"));
    mapStudent.insert(map<int, string>::value_type(2, "student_two"));
    mapStudent.insert(map<int, string>::value_type(3, "student_three"));
    map<int, string>::iterator  iter;
    for (iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
    {
        cout << iter->first << " " << iter->second << endl;
    }
}
//第三種:用數組方式插入數據,下面舉例說明
//[cpp] view plain copy
#include <map>  
#include <string>  
#include <iostream>  
using namespace std;
int main()
{
    map<int, string> mapStudent;
    mapStudent[1] = "student_one";
    mapStudent[2] = "student_two";
    mapStudent[3] = "student_three";
    map<int, string>::iterator  iter;
    for (iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
    {
        cout << iter->first << "   " << iter->second << endl;
    }
}
//以上三種用法,雖然都可以實現數據的插入,但是它們是有區別的,當然了第一種和第二種在效果上是完成一樣的,
//用insert函數插入數據,在數據的插入上涉及到集合的唯一性這個概念,即當map中有這個關鍵字時,
//insert操作是插入數據不了的,但是用數組方式就不同了,它可以覆蓋以前該關鍵字對應的值,用程序說明
//[cpp] view plain copy
//mapStudent.insert(map<int, string>::value_type(1, "student_one"));
//mapStudent.insert(map<int, string>::value_type(1, "student_two"));
//上面這兩條語句執行後,map中1這個關鍵字對應的值是"student_one",第二條語句並沒有生效,
//那麼這就涉及到我們怎麼知道insert語句是否插入成功的問題了,可以用pair來獲得是否插入成功,程序如下
//[cpp] view plain copy
//Pair<map<int, string>::iterator, bool> Insert_Pair;
//Insert_Pair = mapStudent.insert(map<int, string>::value_type(1, "student_one"));
//我們通過pair的第二個變量來知道是否插入成功,它的第一個變量返回的是一個map的迭代器,
//如果插入成功的話Insert_Pair.second應該是true的,否則爲false。
//下面給出完成代碼,演示插入成功與否問題
//[cpp] view plain copy
#include <map>  
#include <string>  
#include <iostream>  
using namespace std;
int main()
{
    map<int, string> mapStudent;
    pair<map<int, string>::iterator, bool> Insert_Pair;
    Insert_Pair = mapStudent.insert(pair<int, string>(1, "student_one"));
    if(Insert_Pair.second == true)
    {
        cout << "Insert Successfully" << endl;
    }
    else
    {
        cout << "Insert Failure" << endl;
    }
    Insert_Pair = mapStudent.insert(pair<int, string>(1, "student_two"));
    if(Insert_Pair.second == true)
    {
        cout << "Insert Successfully" << endl;
    }
    else
    {
        cout << "Insert Failure" << endl;
    }
    map<int, string>::iterator  iter;
    for (iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
    {
        cout << iter->first << "   " << iter->second << endl;
    }
}
//大家可以用如下程序,看下用數組插入在數據覆蓋上的效果
//[cpp] view plain copy
#include <map>  
#include <string>  
#include <iostream>  
using namespace std;
int main()
{
    map<int, string> mapStudent;
    mapStudent[1] = "student_one";
    mapStudent[1] = "student_two";
    mapStudent[2] = "student_three";
    map<int, string>::iterator  iter;
    for (iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
    {
        cout << iter->first << "   " << iter->second << endl;
    }
}
//3.map的大小
//在往map裏面插入了數據,我們怎麼知道當前已經插入了多少數據呢,可以用size函數,用法如下:
//[cpp] view plain copy
//int nSize = mapStudent.size();
//4.數據的遍歷
//這裏也提供三種方法,對map進行遍
//第一種:應用前向迭代器,上面舉例程序中到處都是了,略過不表
//第二種:應用反相迭代器,下面舉例說明,要體會效果,請自個動手運行程序
//[cpp] view plain copy
#include <map>  
#include <string>  
#include <iostream>  
using namespace std;
int main()
{
    map<int, string> mapStudent;
    mapStudent.insert(pair<int, string>(1, "student_one"));
    mapStudent.insert(pair<int, string>(2, "student_two"));
    mapStudent.insert(pair<int, string>(3, "student_three"));
    map<int, string>::reverse_iterator  iter;
    for (iter = mapStudent.rbegin(); iter != mapStudent.rend(); iter++)
    {
        cout << iter->first << "   " << iter->second << endl;
    }
}
//第三種:用數組方式,程序說明如下
//[cpp] view plain copy
#include <map>  
#include <string>  
#include <iostream>  
using namespace std;
int main()
{
    map<int, string> mapStudent;
    mapStudent.insert(pair<int, string>(1, "student_one"));
    mapStudent.insert(pair<int, string>(2, "student_two"));
    mapStudent.insert(pair<int, string>(3, "student_three"));
    int nSize = mapStudent.size();
        //此處有誤,應該是 for(int nIndex = 1; nIndex <= nSize; nIndex++)   
        //by rainfish  
    for (int nIndex = 0; nIndex < nSize; nIndex++)
    {
        cout << mapStudent[nIndex] << endl;
    }
}
//5.數據的查找(包括判定這個關鍵字是否在map中出現)
//在這裏我們將體會,map在數據插入時保證有序的好處。
//要判定一個數據(關鍵字)是否在map中出現的方法比較多,這裏標題雖然是數據的查找,在這裏將穿插着大量的map基本用法。
//這裏給出三種數據查找方法
//第一種:用count函數來判定關鍵字是否出現,其缺點是無法定位數據出現位置, 由於map的特性,一對一的映射關係,
//就決定了count函數的返回值只有兩個,要麼是0,要麼是1,出現的情況,當然是返回1了
//第二種:用find函數來定位數據出現位置,它返回的一個迭代器,當數據出現時,它返回數據所在位置的迭代器,
//如果map中沒有要查找的數據,它返回的迭代器等於end函數返回的迭代器,程序說明
//[cpp] view plain copy
#include <map>  
#include <string>  
#include <iostream>  
using namespace std;
int main()
{
    map<int, string> mapStudent;
    mapStudent.insert(pair<int, string>(1, "student_one"));
    mapStudent.insert(pair<int, string>(2, "student_two"));
    mapStudent.insert(pair<int, string>(3, "student_three"));
    map<int, string>::iterator iter;
    iter = mapStudent.find(1);
    if (iter != mapStudent.end())
    {
        cout << "Find, the value is " << iter->second << endl;
    }
    else
    {
        cout << "Do not Find" << endl;
    }
}
//第三種:這個方法用來判定數據是否出現,是顯得笨了點,但是,我打算在這裏講解
//Lower_bound函數用法,這個函數用來返回要查找關鍵字的下界(是一個迭代器)
//Upper_bound函數用法,這個函數用來返回要查找關鍵字的上界(是一個迭代器)
//例如:map中已經插入了1,2,3,4的話,如果lower_bound(2)的話,返回的2,而upper - bound(2)的話,返回的就是3
//Equal_range函數返回一個pair,pair裏面第一個變量是Lower_bound返回的迭代器,pair裏面第二個
//迭代器是Upper_bound返回的迭代器,如果這兩個迭代器相等的話,則說明map中不出現這個關鍵字,程序說明
//[cpp] view plain copy
#include <map>  
#include <string>  
#include <iostream>  
using namespace std;
int main()
{
    map<int, string> mapStudent;
    mapStudent[1] = "student_one";
    mapStudent[3] = "student_three";
    mapStudent[5] = "student_five";
    map<int, string>::iterator  iter;
    iter = mapStudent.lower_bound(2);
    {
        //返回的是下界3的迭代器  
        cout << iter->second << endl;
    }
    iter = mapStudent.lower_bound(3);
    {
        //返回的是下界3的迭代器  
        cout << iter->second << endl;
    }
    iter = mapStudent.upper_bound(2);
    {
        //返回的是上界3的迭代器  
        cout << iter->second << endl;
    }
    iter = mapStudent.upper_bound(3);
    {
        //返回的是上界5的迭代器  
        cout << iter->second << endl;
    }
    pair<map<int, string>::iterator, map<int, string>::iterator> mapPair;
    mapPair = mapStudent.equal_range(2);
    if (mapPair.first == mapPair.second)
    {
        cout << "Do not Find" << endl;
    }
    else
    {
        cout << "Find" << endl;
    }
    mapPair = mapStudent.equal_range(3);
    if (mapPair.first == mapPair.second)
    {
        cout << "Do not Find" << endl;
    }
    else
    {
        cout << "Find" << endl;
    }
}
//6.  數據的清空與判空
//清空map中的數據可以用clear()函數,判定map中是否有數據可以用empty()函數,它返回true則說明是空map
//7.  數據的刪除
//這裏要用到erase函數,它有三個重載了的函數,下面在例子中詳細說明它們的用法
//[cpp] view plain copy
#include <map>  
#include <string>  
#include <iostream>  
using namespace std;
int main()
{
    map<int, string> mapStudent;
    mapStudent.insert(pair<int, string>(1, "student_one"));
    mapStudent.insert(pair<int, string>(2, "student_two"));
    mapStudent.insert(pair<int, string>(3, "student_three"));
    //如果你要演示輸出效果,請選擇以下的一種,你看到的效果會比較好  
    //如果要刪除1,用迭代器刪除  
    map<int, string>::iterator iter;
    iter = mapStudent.find(1);
    mapStudent.erase(iter);
    //如果要刪除1,用關鍵字刪除  
    int n = mapStudent.erase(1);//如果刪除了會返回1,否則返回0  
    //用迭代器,成片的刪除  
    //一下代碼把整個map清空  
    mapStudent.erase(mapStudent.begin(), mapStudent.end());
    //成片刪除要注意的是,也是STL的特性,刪除區間是一個前閉後開的集合  
    //自個加上遍歷代碼,打印輸出吧  
}
//8.其他一些函數用法
//這裏有swap, key_comp, value_comp, get_allocator等函數,感覺到這些函數在編程用的不是很多,
//略過不表,有興趣的話可以自個研究
//9.排序
//這裏要講的是一點比較高深的用法了, 排序問題,STL中默認是採用小於號來排序的,
//以上代碼在排序上是不存在任何問題的,因爲上面的關鍵字是int型,它本身支持小於號運算,在一些特殊情況,
//比如關鍵字是一個結構體,涉及到排序就會出現問題,因爲它沒有小於號操作,insert等函數在編譯的時候過不去,
//下面給出兩個方法解決這個問題
//第一種:小於號重載,程序舉例
//[cpp] view plain copy
#include <map>  
#include <string>  
using namespace std;
typedef struct tagStudentInfo
{
    int      nID;
    string   strName;
}StudentInfo, *PStudentInfo;  //學生信息  
int main()
{
    int nSize;
    //用學生信息映射分數  
    map<StudentInfo, int>mapStudent;
    map<StudentInfo, int>::iterator iter;
    StudentInfo studentInfo;
    studentInfo.nID = 1;
    studentInfo.strName = "student_one"
        mapStudent.insert(pair<StudentInfo, int>(studentInfo, 90));
    studentInfo.nID = 2;
    studentInfo.strName = "student_two";
    mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80));
    for (iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
        cout << iter->first.nID << endl << iter->first.strName << endl << iter->second << endl;
}
//以上程序是無法編譯通過的,只要重載小於號,就OK了,如下:
//[cpp] view plain copy
typedef struct tagStudentInfo
{
    int      nID;
    string   strName;
    bool operator < (tagStudentInfo const& _A) const
    {
        //這個函數指定排序策略,按nID排序,如果nID相等的話,按strName排序  
        if(nID < _A.nID)  return true;
        if(nID == _A.nID) return strName.compare(_A.strName) < 0;
        return false;
    }
}StudentInfo, *PStudentInfo;  //學生信息  
//第二種:仿函數的應用,這個時候結構體中沒有直接的小於號重載,程序說明
//[cpp] view plain copy
#include <map>  
#include <string>  
using namespace std;
typedef struct tagStudentInfo
{
    int      nID;
    string   strName;
}StudentInfo, *PStudentInfo;  //學生信息  
class sort
{
public:
    bool operator() (StudentInfo const &_A, StudentInfo const &_B) const
    {
        if(_A.nID < _B.nID) return true;
        if(_A.nID == _B.nID) return _A.strName.compare(_B.strName) < 0;
        return false;
    }
};
int main()
{
    //用學生信息映射分數  
    map<StudentInfo, int, sort>mapStudent;
    StudentInfo studentInfo;
    studentInfo.nID = 1;
    studentInfo.strName = "student_one";
    mapStudent.insert(pair<StudentInfo, int>(studentInfo, 90));
    studentInfo.nID = 2;
    studentInfo.strName = "student_two";
    mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80));
}
//10.另外
//由於STL是一個統一的整體,map的很多用法都和STL中其它的東西結合在一起,比如在排序上,
//這裏默認用的是小於號,即less<>,如果要從大到小排序呢,這裏涉及到的東西很多,在此無法一一加以說明。
//還要說明的是,map中由於它內部有序,由紅黑樹保證,因此很多函數執行的時間複雜度都是log2N的,
//如果用map函數可以實現的功能,而STL  Algorithm也可以完成該功能,建議用map自帶函數,效率高一些。
//下面說下,map在空間上的特性,否則,估計你用起來會有時候表現的比較鬱悶,
//由於map的每個數據對應紅黑樹上的一個節點,這個節點在不保存你的數據時,是佔用16個字節的,
//一個父節點指針,左右孩子指針,還有一個枚舉值(標示紅黑的,相當於平衡二叉樹中的平衡因子),
//我想大家應該知道,這些地方很費內存了。
/*
multimap 類

標準模板庫多重映射類用於存儲和檢索集合中的數據,此集合中的每個元素均爲包含數據值和排序鍵的元素對。 
鍵值不需要唯一,用於自動排序數據。 可以直接更改多重映射中的元素值,但不能直接更改其關聯鍵值。
必須先刪除與舊元素關聯的鍵值,才能插入與新元素關聯的新鍵值。

語法
template <
    class Key,
    class Type,
    class Traits = less<Key>,
    class Allocator = allocator<pair <const Key, Type> >
> class multimap;
    參數
        Key
        要存儲在多重映射中的鍵數據類型。

        Type
        要存儲在多重映射中的元素數據類型。

        Traits
        一種提供函數對象的類型,該函數對象可將兩個元素值作爲排序鍵進行比較,以確定其在多重映射中的相對順序。 默認值是二元謂詞 less<Key>。

        在 C++ 14 中可以通過指定沒有類型參數的 std::less<> 或 std::greater<> 謂詞來啓用異類查找。 有關詳細信息,請參閱8e915ca1 - 19ba - 4f0d - 93c8 - e2c3bfd638eb#sequence_containers

        Allocator
        一種表示存儲的分配器對象的類型,該分配器對象封裝有關映射的內存分配和解除分配的詳細信息。 此參數爲可選參數,默認值爲 allocator<pair <const Key, Type> >。

        備註
        STL 多重映射類是:

        大小可變的關聯容器,支持基於關聯鍵值高效檢索元素值。

        可逆,因爲它提供雙向迭代器來訪問其元素。

        有序,因爲它的元素在容器中根據指定的比較函數按鍵值排序。

        多個,它的元素不需要具有唯一鍵,因此一個鍵值可具有多個相關聯的元素數據值。

        關聯容器對,因爲它的元素數據值與其鍵值不同。

        模板類,因爲它提供的功能是一般性的功能,因此與作爲元素或鍵包含的特定數據類型無關。
        用於元素和鍵的數據類型作爲類模板以及比較函數和分配器中的參數指定。

        映射類提供的迭代器是雙向迭代器,但類成員函數 insert 和 multimap 具有將較弱輸入迭代器作爲模板參數的版本,
        較弱輸入迭代器的功能要求比雙向迭代器類保證的功能要求更少。 不同的迭代器概念形成一個系列,
        通過它們的功能優化相關聯。 每個迭代器概念有它自己的一套要求,
        使用這些概念的算法必須根據迭代器類型提供的要求限制它們的假設。 可以假定輸入迭代器可取消引用以引用某個對象,
        並可遞增到序列中的下一迭代器。 這是最小的功能集,
        但足以按有意義的方式提供類成員函數的上下文中的迭代器範圍[First, Last)。

        容器類型選擇通常應根據應用程序所需的搜索和插入的類型。 關聯容器針對查找、插入和移除操作進行了優化。
        顯式支持這些操作的成員函數較爲高效,執行這些操作的時間與容器中元素數量的對數平均成比例。
        插入元素不會使迭代器失效,移除元素僅會使專門指向已移除元素的迭代器失效。

        當應用程序滿足將值與其鍵關聯的條件時,應選擇多重映射作爲關聯容器。 此類結構的模型是關鍵字排序列表,
        這些關鍵字具有提供定義等的關聯字符串值,並且並非始終唯一定義。 如果關鍵字經過唯一定義以使鍵唯一,
        則應選擇映射作爲容器。 另一方面,如果僅存儲關鍵字列表,則應使用集作爲正確容器。 如果允許關鍵字多次出現,
        則應使用多重集合作爲適當的容器結構。

        多重映射通過調用存儲的 key_compare 類型的函數對象,對它控制的序列進行排序。 此存儲的對象是比較函數,
        可通過調用成員函數 key_comp 訪問。 通常,元素僅需小於比較元素即可建立此順序;因此,給定任意兩個元素,
        可以確定這兩個元素等效(即兩者均不小於對方)或其中一個小於另一個。 這將導致在非等效元素之間進行排序。
        在技術性更強的說明中,比較函數是一個二元謂詞,在標準數學的意義上引發嚴格弱排序。 二元謂詞 f(x, y) 
        是包含兩個參數對象(x 和y)以及一個返回值(true 或 false)的函數對象。 如果二元謂詞具有自反性、
        反對稱性和傳遞性且等效可傳遞,對集進行的排序將爲嚴格弱排序,其中兩個對象x 和 y 定義爲在 f(x, y) 
        和 f(y, x) 均爲 false 時等效。 如果鍵之間的更強相等條件取代了等效性,則排序將爲總排序(即所有元素彼此排序),
        並且匹配的鍵將難以彼此辨別。

        在 C++ 14 中可以通過指定沒有類型參數的 std::less<> 或 std::greater<> 謂詞來啓用異類查找。
        有關詳細信息,請參閱8e915ca1 - 19ba - 4f0d - 93c8 - e2c3bfd638eb#sequence_containers

        成員
        構造函數
        multimap

        構造一個空的或者是其他某個 multimap 的全部或部分副本的 multimap。

        Typedef
        allocator_type

        一種類型,此類型表示 allocator 對象的 multimap 類。

        const_iterator

        一種類型,此類型提供可讀取 const 中的 multimap 元素的雙向迭代器。

        const_pointer

        一種類型,此類型提供指向 const 中的 multimap 元素的指針。

        const_reference

        一種類型,此類型提供對存儲在 const 中的 multimap 元素的引用(用於讀取和執行 const 操作)。

        const_reverse_iterator

        一種類型,此類型提供可讀取 const 中的任何 multimap 元素的雙向迭代器。

        difference_type

        一種有符號整數類型,此類型可用於表示 multimap 中迭代器指向的元素間範圍內的元素數量。

        iterator

        一種類型,此類型提供引用同一 multimap 中的元素的兩個迭代器之間的差異。

        key_compare

        一種提供函數對象的類型,該函數對象可比較兩個排序鍵以確定 multimap 中兩個元素的相對順序。

        key_type

        一種類型,此類型描述組成 multimap 中每個元素的排序鍵對象。

        mapped_type

        一種類型,此類型表示存儲在 multimap 中的數據類型。

        指針

        一種類型,此類型提供指向 const 中的 multimap 元素的指針。

        引用

        一種類型,此類型提供對存儲在 multimap 中的元素的引用。

        reverse_iterator

        一種類型,此類型提供可讀取或修改反向 multimap 中的元素的雙向迭代器。

        size_type

        一種無符號整數類型,此類型提供指向 const 中multimap 元素的指針。

        value_type

        一種提供函數對象的類型,該函數對象可將兩個元素作爲排序鍵比較以確定它們在 multimap 中的相對順序。

        成員函數
        begin

        返回一個迭代器,此迭代器用於發現 multimap 中的第一個元素。

        cbegin

        返回一個常量迭代器,此迭代器用於發現 multimap 中的第一個元素。

        cend

        返回一個常量迭代器,此迭代器用於發現 multimap 中最後一個元素之後的位置。

        清除

        清除 multimap 的所有元素。

        count

        返回 multimap 中其鍵與指定爲參數的鍵匹配的元素數量。

        crbegin

        返回一個常量迭代器,此迭代器用於發現反向 multimap 中的第一個元素。

        crend

        返回一個常量迭代器,此迭代器用於發現反向 multimap 中最後一個元素之後的位置。

        emplace

        將就地構造的元素插入到 multimap。

        emplace_hint

        將就地構造的元素插入到 multimap,附帶位置提示

        空

        測試 multimap 是否爲空。

        end

        返回一個迭代器,此迭代器用於發現 multimap 中最後一個元素之後的位置。

        equal_range

        查找其中元素的鍵與指定值匹配的元素範圍。

        erase

        從 multimap 中的指定位置移除一個元素或元素範圍,或者移除與指定鍵匹配的元素。

        find

        返回一個迭代器,此迭代器用於發現 multimap 中其鍵與指定鍵等效的元素的第一個位置。

        get_allocator

        返回用於構造 allocator 的 multimap 對象的副本。

        插入

        將一個元素或元素範圍插入到 multimap。

        key_comp

        檢索用於對 multimap 中的鍵進行排序的比較對象副本。

        lower_bound

        返回一個迭代器,此迭代器指向 multimap 中其鍵等於或大於指定鍵的第一個元素。

        max_size

        返回 multimap 的最大長度。

        rbegin

        返回一個迭代器,此迭代器用於發現反向 multimap 中的第一個元素。

        rend

        返回一個迭代器,此迭代器用於發現反向 multimap 中最後一個元素之後的位置。

        size

        返回 multimap 中的元素數量。

        swap

        交換兩個 multimap 的元素。

        upper_bound

        返回一個迭代器,此迭代器指向 multimap 中其鍵大於指定鍵的第一個元素。

        value_comp

        此成員函數返回一個函數對象,該函數對象可通過比較 multimap 中元素的鍵值來確定元素順序。

        運算符
        operator =

        將一個 multimap 中的元素替換爲另一 multimap 副本。

        要求
        標頭:<map>

    命名空間: std

          (key, value) 對作爲 pair 類型的對象存儲在多重映射中。 此對類需要標頭 <utility>,<map> 自動包括此標頭。
          */


/**
*@File MultiMapDemo.cpp
*
*@Author: Bob
*
*@Create Time: 2016-12-1 11:57:06
*
*@Last Modify: Bob
*
*@Last Modify Time: 2016-12-1 11:57:06
*
*@Description:
*   multimap多重映照容器
*   multimap多重映照容器:容器的數據結構採用紅黑樹進行管理
*    multimap的所有元素都是pair:第一元素爲鍵值(key),不能修改;第二元素爲實值(value),可被修改
*    multimap特性以及用法與map完全相同,唯一的差別在於:
*   允許重複鍵值的元素插入容器(使用了RB-Tree的insert_equal函數)
*   因此:
*      鍵值key與元素value的映照關係是多對多的關係
*      沒有定義[]操作運算
*/

#include <iostream>
#include <string>
#include <map>



int main(int argc, char* argv[])
{
    std::multimap<std::string, int> myMultiMap;

    // 插入
    myMultiMap.insert(std::pair<std::string, int>("Jack", 1));
    myMultiMap.insert(std::pair<std::string, int>("Jack", 2));
    myMultiMap.insert(std::pair<std::string, int>("Bob", 1));
    myMultiMap.insert(std::pair<std::string, int>("Navy", 3));
    myMultiMap.insert(std::pair<std::string, int>("Demo", 4));
    myMultiMap.insert(std::pair<std::string, int>("Bob", 5));

    // 遍歷
    std::cout << "================All member" << std::endl;
    for (std::multimap<std::string, int>::iterator iter = myMultiMap.begin(); iter != myMultiMap.end(); ++iter)
    {
        std::cout << (*iter).first << ":" << (*iter).second << std::endl;
    }


    // 統計key爲"Jack"的數目
    std::string strFind = "Jack";
    unsigned int uCount = myMultiMap.count(strFind);
    if (uCount == 0)
    {
        std::cout << "================Count " << strFind << ":0" << std::endl;
    }
    else
    {
        std::cout << "================Count " << strFind << ":" << uCount << std::endl;
        std::multimap<std::string, int>::iterator iter = myMultiMap.find(strFind);
        if (iter != myMultiMap.end())
        {
            for (unsigned int i = 0; i < uCount; ++i)
            {
                std::cout << (*iter).first << ":" << (*iter).second << std::endl;
                iter++;
            }
        }
    }


    std::cout << "================use equal_range" << std::endl;
    typedef std::multimap<std::string, int>::iterator MultiMapIterator;
    std::pair<MultiMapIterator, MultiMapIterator> iterPair = myMultiMap.equal_range("Jack");
    for (MultiMapIterator it = iterPair.first; it != iterPair.second; ++it)
    {
        std::cout << (*it).first << ":" << (*it).second << std::endl;
    }


    // 刪除所有key爲"Bob"的鍵值對
    myMultiMap.erase("Bob");
    std::cout << "================After erase Bob" << std::endl;
    for (std::multimap<std::string, int>::iterator iter = myMultiMap.begin(); iter != myMultiMap.end(); ++iter)
    {
        std::cout << (*iter).first << ":" << (*iter).second << std::endl;
    }


    // 刪除重複的key
    MultiMapIterator iter = myMultiMap.find("Jack");
    myMultiMap.erase(iter);
    std::cout << "================Use unique key, erase \"Jack\" " << std::endl;
    for (std::multimap<std::string, int>::iterator iter = myMultiMap.begin(); iter != myMultiMap.end(); ++iter)
    {
        std::cout << (*iter).first << ":" << (*iter).second << std::endl;
    }

    system("pause");
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章