某網友問:“map中怎麼設置多個key值進行排序?”
在C++中,map是典型的關聯容器或者叫映射容器(associative container),其中的每一個元素都是由key-value這樣成對出現的內容組成的,比如學號和學生之類具有一一對應關係的情形,學號可以作爲key,學生對象可以作爲key所對應的value。很顯然這種情況下的key只有一個值,但是,在實際工作中,我們可能會經常需要使用多個值組合起來作爲key的情況,比如我們要按照學生的視力和身高進行排序,以決定學生的座位排在前面還是後面,而且還是假定要用map來解決這樣的問題(當然,這樣的問題有很多其它的解決辦法),那應該怎麼辦呢?
(1) 單值作爲key的情形
我們知道map在缺省狀態下,其數據是按照key的升序進行排列的。假定我們有一個Student類,聲明如下:
class Student
{
private:
int id; // 學號
string name; // 姓名
float eyesight; // 視力
float height; // 身高
float chinese; // 語文成績
float english; // 英文成績
float math; // 數學成績
public:
Student(int id, string name,floateyesight, float height,float chinese, float english,float math)
{
this->id = id;
this->name = name;
this->eyesight = eyesight;
this->height = height;
this->chinese = chinese;
this->english = english;
this->math = math;
}
int get_id()
{
return id;
}
string get_name()
{
return name;
}
float get_eyesight()
{
return eyesight;
}
float get_height()
{
return height;
}
float get_chinese()
{
return chinese;
}
float get_english()
{
return english;
}
float get_math()
{
return math;
}
};
那麼下面的程序:
int main(int argc,char**argv)
{
map<int, Student> stu_map; // int作爲key的類型,Student作爲value的類型
stu_map.insert(make_pair(4,Student(4, "Dudley",1.1f, 170.2f, 90.5f, 89.5f, 93.0)));
stu_map.insert(make_pair(3,Student(3, "Chris", 1.1f, 163.4f, 93.5f,90.0f, 83.5f)));
stu_map.insert(make_pair(2,Student(2, "Bob", 1.5f, 166.6f, 86.0f,98.5f, 85.0f)));
stu_map.insert(make_pair(1,Student(1, "Andrew", 1.5f, 173.2f, 98.5f,100.0f, 100.f)));
map<int, Student>::iterator iter;
for(iter = stu_map.begin(); iter != stu_map.end();++iter)
{
cout<< iter->first << "\t"<< iter->second.get_name() << endl;
}
return 0;
}
就會按照學號的升序給出輸出:
1 Andrew
2 Bob
3 Chris
4 Dudley
這是缺省的情形,如果要將學生的姓名按照學號的降序輸出,那麼僅需將上面main函數中的
map<int,Student> stu_map;改爲
map<int,Student, greater<int> > stu_map;
以及
map<int,Student>::iterator iter;改爲
map<int,Student, greater<int> >::iteratoriter;
即可。
其實,map<int,Student> stu_map;這是一種缺省的情況,它和
map<int,Student, less<int> > stu_map;是一樣的。
(2) 多值組合作爲key的情形
現在,我們來看看多個值組合起來作爲key的情況,爲此,我們需要爲key定義一個類,如下:
class key
{
public:
float eyesight;
float height;
key(float x, floaty):eyesight(x), height(y)
{
}
friend bool operator < (constkey&,const key&);
};
bool operator < (constkey& key1,const key& key2)
{
// 按eyesight升序 + height升序排列
if(key1.eyesight != key2.eyesight)
return (key1.eyesight < key2.eyesight);
else
return (key1.height < key2.height);
// 按eyesight降序 + height降序排列
//if(key1.eyesight != key2.eyesight)
// return(key1.eyesight > key2.eyesight);
//else
// return(key1.height > key2.height);
// 按eyesight升序 + height降序排列
//if(key1.eyesight != key2.eyesight)
// return(key1.eyesight < key2.eyesight);
//else
// return(key1.height > key2.height);
// 按eyesight降序 + height升序排列
//if(key1.eyesight != key2.eyesight)
// return(key1.eyesight > key2.eyesight);
//else
// return(key1.height < key2.height);
}
再修改main函數如下:
int main(int argc,char**argv)
{
map<key,Student> stu_map;
Studentstu4(4, "Dudley",1.1f, 170.2f, 90.5f, 89.5f, 93.0);
Studentstu3(3, "Chris", 1.1f, 163.4f, 93.5f,90.0f, 83.5f);
Studentstu2(2, "Bob", 1.5f, 166.6f, 86.0f,98.5f, 85.0f);
Studentstu1(1, "Andrew", 1.5f, 173.2f, 98.5f,100.0f, 100.f);
stu_map.insert(make_pair(key(stu4.get_eyesight(),stu4.get_height()), stu4));
stu_map.insert(make_pair(key(stu3.get_eyesight(),stu3.get_height()), stu3));
stu_map.insert(make_pair(key(stu2.get_eyesight(),stu2.get_height()), stu2));
stu_map.insert(make_pair(key(stu1.get_eyesight(),stu1.get_height()), stu1));
map<key,Student>::iterator iter;
for(iter = stu_map.begin(); iter != stu_map.end();++iter)
{
cout<< iter->first.eyesight << "\t"<< iter->first.height << "\t" << iter->second.get_id()<<"\t" <<iter->second.get_name() << endl;
}
return 0;
}
那麼輸出結果爲:
1.1 163.4 3 Chris
1.1 170.2 4 Dudley
1.5 166.6 2 Bob
1.5 173.2 1 Andrew
從上面的輸出,我們可以很明顯地看到,是按照視力升序和升高升序輸出的,另外三種可能的排序情況,也在類key的操作符“<”的重載函數中,用註釋的形式給出了。
(3)結論
1.通常我們不用STL algorithm中的sort函數,來對一個map進行排序,而對vector的元素進行排序則可以很方面地使用sort函數;
2.多值組合作爲key的情況,需要我們自己定義一個key類,並在該類中重載操作符“<”。
附兩個值作爲key的情況之完整的實驗代碼如下:
#include <iostream>
#include <map>
#include <string>
using namespace std;
class key
{
public:
float eyesight;
float height;
key(float x, floaty):eyesight(x), height(y)
{
}
friend bool operator < (constkey&,const key&);
};
bool operator < (constkey& key1,const key& key2)
{
// 按eyesight升序 + height升序排列
if(key1.eyesight != key2.eyesight)
return (key1.eyesight < key2.eyesight);
else
return (key1.height < key2.height);
// 按eyesight降序 + height降序排列
//if(key1.eyesight != key2.eyesight)
// return(key1.eyesight > key2.eyesight);
//else
// return(key1.height > key2.height);
// 按eyesight升序 + height降序排列
//if(key1.eyesight != key2.eyesight)
// return(key1.eyesight < key2.eyesight);
//else
// return(key1.height > key2.height);
// 按eyesight降序 + height升序排列
//if(key1.eyesight != key2.eyesight)
// return(key1.eyesight > key2.eyesight);
//else
// return(key1.height < key2.height);
}
class Student
{
private:
int id; //學號
string name; // 姓名
float eyesight; //視力
float height; //身高
float chinese; //語文成績
float english; //英文成績
float math; //數學成績
public:
Student(int id, string name,floateyesight,float height,float chinese,float english,float math)
{
this->id = id;
this->name = name;
this->eyesight = eyesight;
this->height = height;
this->chinese = chinese;
this->english = english;
this->math = math;
}
int get_id()
{
return id;
}
string get_name()
{
return name;
}
float get_eyesight()
{
return eyesight;
}
float get_height()
{
return height;
}
float get_chinese()
{
return chinese;
}
float get_english()
{
return english;
}
float get_math()
{
return math;
}
};
int main(int argc,char**argv)
{
map<key,Student> stu_map;
Studentstu4(4, "Dudley",1.1f, 170.2f, 90.5f, 89.5f, 93.0);
Studentstu3(3, "Chris", 1.1f, 163.4f, 93.5f,90.0f, 83.5f);
Studentstu2(2, "Bob", 1.5f, 166.6f, 86.0f,98.5f, 85.0f);
Studentstu1(1, "Andrew", 1.5f, 173.2f, 98.5f,100.0f, 100.f);
stu_map.insert(make_pair(key(stu4.get_eyesight(),stu4.get_height()), stu4));
stu_map.insert(make_pair(key(stu3.get_eyesight(),stu3.get_height()), stu3));
stu_map.insert(make_pair(key(stu2.get_eyesight(),stu2.get_height()), stu2));
stu_map.insert(make_pair(key(stu1.get_eyesight(),stu1.get_height()), stu1));
map<key,Student>::iterator iter;
for(iter = stu_map.begin(); iter != stu_map.end();++iter)
{
cout<< iter->first.eyesight << "\t"<< iter->first.height << "\t" << iter->second.get_id()<<"\t" <<iter->second.get_name() << endl;
}
return 0;
}