經常碰到結構體排序的問題,在此總結一下。
以一個簡單的例題開始:
例1、有三個人(Person結構體),每個人都有name(string型)和age(int型)兩個屬性,現在需要按照下面的規則排序:先以姓名按從小到大排序(如abc<abd),如果姓名相同,則按照年齡從大到小排序。
#include<iostream>
#include<string>
using namespace std;
struct Person{
string name;
int age;
};
void exchange(Person &a,Person &b){
//注意交換的時候,中間變量是結構體類型,而不是基本數據類型(int,char,string)等。
Person temp;
temp=a;
a=b;
b=temp;
}
int main(){
Person p[3];
int i,j;
for(i=0;i<3;i++){
cin>>p[i].name>>p[i].age;
}
//冒泡排序實現
for(i=0;i<3;i++){
for(j=0;j<3-i-1;j++){
if(p[j].name>p[j+1].name){
exchange(p[j],p[j+1]);
} else if(p[j].name==p[j+1].name){
if(p[j].age<p[j+1].age){
exchange(p[j],p[j+1]);
}
}
}
}
//依次輸出
for(i=0;i<3;i++){
cout<<p[i].name<<' '<<p[i].age<<endl;
}
}
這個代碼是我最初寫的,毫無技術含量,參加過ACM或者程序競賽的朋友一看就知道這樣做太復雜,因為有一個簡單的sort函數,只要一行代碼即可實現。
sort函數首先是一個排序函數,不僅可以用來給數字排序,還可以給字符串排序,默認的是升序,如果需要降序的話,可以自己寫一個cmp回調函數(函數名可自擬,通常用cmp),然后在sort函數中,加上(cmp)函數名即可。
例2、隨機產生10個數,並且從大到小輸出
#include<iostream>
#include<algorithm>
#include<cstdlib>
bool cmp(int a,int b){
return a>b;
}
using namespace std;
int main(){
int A[10],i;
for(i=0;i<10;i++){
A[i]=rand();
}
sort(A,A+10,cmp);
for(i=0;i<10;i++){
cout<<A[i]<<' ';
}
}
注意:使用sort函數,必須要加#include<algorithm>頭文件。在sort函數中,第一個參數為數組(字符串)名,第二個參數為排序范圍,是從A到A+n(n為長度),第三個參數可省,省略后則代表默認升序,加上自己寫的cmp函數,即可按照cmp中的規定進行排序。
既然sort函數這么神奇,那他肯定也是可以對結構體或者對象進行排序的。比如例1可以用如下代碼:
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
struct Person{
string name;
int age;
};
bool cmp(Person a,Person b){
if(a.name!=b.name){
return a.name<b.name;
} else {
return a.age>b.age;
}
}
int main(){
Person p[3];
int i,j;
for(i=0;i<3;i++){
cin>>p[i].name>>p[i].age;
}
//排序
sort(p,p+3,cmp);
//依次輸出
for(i=0;i<3;i++){
cout<<p[i].name<<' '<<p[i].age<<endl;
}
}
對於稍微簡單的問題便可以用這種方法。如果問題稍復雜,也就是結構體中的屬性太多了,於是在cmp函數中的判斷語句就增加了,此時要注意寫判斷語句的時候一定要弄清楚先判斷什么,在判斷什么,怎么組織語句等。
比如例3、在這里我們需要對N個人(Person)進行排序,規則如下:每個人有3個屬性,name(string型),age(int型),height(int型)。優先按照name由大到小排名,name相同的則按照age由大到小排序,age相同的則按照height由大到小排序。
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
struct Person{
string name;
int age;
int height;
};
bool cmp(Person a,Person b){
if(a.name!=b.name){
return a.name>b.name;
}
if(a.name==b.name && a.age!=b.age){
return a.age>b.age;
}
if(a.name==b.name && a.age==b.age){
return a.height>b.height;
}
}
int main(){
int n;
cin>>n;
Person p[n];
int i,j;
for(i=0;i<n;i++){
cin>>p[i].name>>p[i].age>>p[i].height;
}
//排序
sort(p,p+n,cmp);
//依次輸出
for(i=0;i<n;i++){
cout<<p[i].name<<' '<<p[i].age<<' '<<p[i].height<<endl;
}
}
其實,對於結構體或者對象排序時,最關鍵的是寫cmp函數。另外,如果只是對一組數據(一串個數字或者字符串)反向排序后輸出,如果只是關心輸出,則可以取巧,直接用sort函數,不用寫cmp回調函數,直接在輸出的時候,從length-1開始倒序輸出。
