經常碰到結構體排序的問題,在此總結一下。
以一個簡單的例題開始:
例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開始倒序輸出。