close

按此前往C++完整教學目錄

 

 

映射(map)複映射(multimap)

(1) map以及multimap中,一個節點所存取的資料有兩種,一為索引(key),一為資料值(value)

(2) map中,一個索引只能對應一個資料值;而在multimap中,一個索引可以對應多個資料值。此二容器之中各節點的排列順序,是以索引的大小來做排列。預設是依索引的ASCII碼由小排到大。

(3) 使用者不能隨意修改某資料的索引,但可以修改某索引上的資料值。

(4) 一個映射或者複映射中,不容許兩個重複相同的索引。

(5) 資料值的資料型態,可為一般資料型態(intbool…)或是類別物件

(6) 無論使用映射還是複映射,均需在標頭檔寫下#include <map>

 

1. 建構:

映射種類<索引資料型態 , 資料的資料型態> 名稱;

映射種類<索引資料型態 , 資料的資料型態 , 雙元判斷式> 名稱;

註一:映射種類可為mapmultimap

註二:以上的第一種建構方法,其實是默認less<索引資料型態>雙元判斷式

 

 

2. 成對結構資料型態:成對結構(pair structure)C++內建的樣板結構,在建構映射和複映射時需要用到。成對結構有兩個成員:firstsecond,這兩個成員可以為不同的資料型態。建立一個成對結構有以下2種方法:

(1) pair<成員first的資料型態 , 成員second的資料型態> 成對結構名稱(成員first的值 , 成員second的值);

舉例:

pair<string , int> tt1("國文",98);  //建構一個成對結構tt1

pair<string , int> tt2("英文",60);  //建構一個成對結構tt2

cout<<tt1.first<<"考了"<<tt1.second<<"分。"<<endl;  //顯示:國文考了98分。

cout<<tt2.first<<"考了"<<tt2.second<<"分。"<<endl;  //顯示:英文考了60分。

(2)利用C++內建樣板函式make_pair()

pair<成員first的資料型態 , 成員second的資料型態> 成對結構名稱;

成對結構名稱 = make_pair(成員first的值 , 成員second的值);

舉例:

pair<string , int> tt1;

tt1=make_pair("國文",98);

pair<string , int> tt2;

tt2=make_pair("英文",60);

cout<<tt1.first<<"考了"<<tt1.second<<"分。"<<endl;  //顯示:國文考了98分。

cout<<tt2.first<<"考了"<<tt2.second<<"分。"<<endl;  //顯示:英文考了60分。

註:要將資料加入映射或者是複映射,必須先將資料轉換成成對結構。其中first對應索引second對應資料值

 

3. 將資料加入映射或複映射(需要使用上一篇所提到的「成對結構」)

(1)若要將資料加入映射,可使用:

(a)映射名稱.insert(成對結構名稱);

其中成對結構的成員first對應索引,成對結構的成員second對應資料。由於在映射中,一個索引只能對應一個資料,故若新加入的成對結構之first的值與映射中的某個索引值相同,則這個新加入的成對結構會被剔除掉,表示加入失敗了。

(b) 映射名稱.insert(迭代器 , 成對結構名稱);

由迭代器位址開始尋找適當的插入位址,以將成對結構加入映射

若加入成功,insert函式回傳此成對結構映射中的位址相應的迭代器。

(c) 映射名稱.insert(迭代器1 , 迭代器2);

迭代器1迭代器2之間(包含迭代器1、不包含迭代器2),的成對結構資料加入此映射,若新加入的成對結構之first的值與映射中的某個索引值相同,則這個新加入的成對結構會被剔除掉,即加入失敗的意思。

(2)若要將資料加入複映射,可使用:

(a)複映射名稱.insert(成對結構名稱);

其中成對結構的成員first對應索引,成對結構的成員second對應資料。

此函式會回傳一個迭代器,和新加入資料的位址對應。

(b) 複映射名稱.insert(迭代器 , 成對結構名稱);

由迭代器位址開始尋找適當的插入位址,以將成對結構加入複映射

並回傳此成對結構複映射中的位址相應的迭代器。

(c) 複映射名稱.insert(迭代器1 , 迭代器2);

迭代器1迭代器2之間(包含迭代器1、不包含迭代器2),的成對結構資料加入複映射

此函式無回傳值。

(3) 範例:

class person

{

public:

string name;

int age;

person(string name_,int age_)

{name=name_;age=age_;}

};

 

void show(person m){

cout<<"我是"<<m.name<<",今年"<<m.age<<"歲。";}

 

int main() {    //主程式在此

person m1("維維",18);

person m2("小藍",19);

person m3("雅芯",24);

person m4("小杜",27);

person m5("木村靜香",17);

 

map<int,person> a;

multimap<int,person> ma;

map<int,person> b;

multimap<int,person> mb;

map<int,person>::iterator i;

map<int,person>::iterator j;

   

a.insert(make_pair(85,m1));

a.insert(make_pair(90,m2));

a.insert(make_pair(77,m3));

a.insert(make_pair(82,m4));

a.insert(make_pair(77,m5));

      

ma.insert(make_pair(85,m1));

ma.insert(make_pair(90,m2));

ma.insert(make_pair(77,m3));

ma.insert(make_pair(82,m4));

ma.insert(make_pair(77,m5));

  

for(i=a.begin();i!=a.end();i++)

{

show(i->second);

cout<<"此次考試考了"<<i->first<<"分。"<<endl;

}

cout<<endl;

/* 顯示為(注意,最後一個加入的m5,是加入失敗的。)

我是雅芯,今年24歲。此次考試考了77分。

我是小杜,今年27歲。此次考試考了82分。

我是維維,今年18歲。此次考試考了85分。

我是小藍,今年19歲。此次考試考了90分。 */

 

for(i=ma.begin();i!=ma.end();i++)

{

show(i->second);

cout<<"此次考試考了"<<i->first<<"分。"<<endl;

}

cout<<endl;

/* 顯示為:

我是雅芯,今年24歲。此次考試考了77分。

我是木村靜香,今年17歲。此次考試考了77分。

我是小杜,今年27歲。此次考試考了82分。

我是維維,今年18歲。此次考試考了85分。

我是小藍,今年19歲。此次考試考了90分。*/

i=ma.begin();

j=ma.end();

j--; j--;

b.insert(i,j);

mb.insert(i,j);

for(i=b.begin();i!=b.end();i++)

{

show(i->second);

cout<<"此次考試考了"<<i->first<<"分。"<<endl;

}

cout<<endl;

/* 顯示為:

我是雅芯,今年24歲。此次考試考了77分。

我是小杜,今年27歲。此次考試考了82分。 */

for(i=mb.begin();i!=mb.end();i++)

{

show(i->second);

cout<<"此次考試考了"<<i->first<<"分。"<<endl;

}

cout<<endl;

/* 顯示為:

我是雅芯,今年24歲。此次考試考了77分。

我是木村靜香,今年17歲。此次考試考了77分。

我是小杜,今年27歲。此次考試考了82分。*/

}

// 註:以上均以分數為索引,可見資料是依分數由小排到大。

 

4. 下標運算子[]

映射可以和矩陣一樣,使用下標運算子[]來直接藉由索引存取資料值。如:

map<int , string> b;

b[85]="唐某";

b[116]="李某";  

cout<<b[85]<<endl;  //顯示:唐某

註:此種方法只有映射能用,對複映射而言,此法是沒有效果的。

 

arrow
arrow
    創作者介紹
    創作者 埃伯 的頭像
    埃伯

    程式語言教學

    埃伯 發表在 痞客邦 留言(0) 人氣()