由2個值組合成key的STL map排序問題

某網友問:“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;
}


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