先說一下,本篇文章我沒有講sort()實現排序的原理,我寫在另一篇文章中了,如果想了解的話,可以看一下,附上鏈接:https://www.cnblogs.com/buanxu/p/12772700.html
sort(v.begin(),v.end(),cmp),它是用來對一組序列進行排序的;有三個參數,前兩個參數是待排序區間;第三個參數可有可無(第三個參數代表比較規則),
沒有第三個參數的時候,sort()默認按升序排列,有第三個參數的時候,可以通過這個參數實現各種各樣的排序,包括降序。sort()函數功能強大就是強大在
第三個參數,后面會講到。
sort()函數除了可以對int型、char型、double型、字符串排序外,還可以實現對結構體、鏈表、pair、vector、等類型進行排序,但需要自己寫比較函數,后面
也會講到。而且sort()既可以對數組排序,也可以對vector容器排序。下面就先說一下sort()只有兩個參數時的用法,看代碼吧,寫的比較詳細,列舉了多種情況
1 #include<iostream> 2 #include<vector> 3 #include<string> 4 #include<algorithm> 5 using namespace std; 6 int main() 7 { 8 int a[10]={6,5,4,8,3,9,7,10,1,2}; 9 char b[8]={'h','z','l','n','m','r','d','g'}; 10 vector<double> v1; 11 vector<string> v2; 12 v1.push_back(3.6); 13 v1.push_back(0.8); 14 v1.push_back(-0.5); 15 v1.push_back(-2.4); 16 v1.push_back(1.2); 17 v2.push_back("abcde"); 18 v2.push_back("fdbcde"); 19 v2.push_back("apcde"); 20 v2.push_back("fdbcdc"); 21 v2.push_back("fdbc"); 22 23 cout<<"對a排序前:"; 24 for(int i=0;i<10;i++) 25 cout<<a[i]<<" "; 26 cout<<"\n對a排序后:"; 27 sort(a+1,a+9); //可以指定任意合法的排序區間,不能越界 28 for(int i=0;i<10;i++) 29 cout<<a[i]<<" "; 30 31 cout<<"\n\n對b排序前:"; 32 for(int i=0;i<8;i++) 33 cout<<b[i]<<" "; 34 cout<<"\n對b排序后:"; 35 sort(b,b+8); //對整個b排序 36 for(int i=0;i<8;i++) 37 cout<<b[i]<<" "; 38 39 cout<<"\n\n對v1排序前:"; 40 for(int i=0;i<v1.size();i++) 41 cout<<v1[i]<<" "; 42 cout<<"\n對v1排序后:"; 43 sort(v1.begin(),v1.end()); 44 for(int i=0;i<v1.size();i++) 45 cout<<v1[i]<<" "; 46 47 cout<<"\n\n對v2排序前:"; 48 for(int i=0;i<v2.size();i++) 49 cout<<v2[i]<<" "; 50 cout<<"\n對v2排序后:"; 51 sort(v2.begin(),v2.end()); 52 for(int i=0;i<v2.size();i++) 53 cout<<v2[i]<<" "; 54 cout<<"\n"; 55 return 0; 56 }
結果如下:
上面列舉了幾種常見數據類型排序后的結果,但是它們都是按升序排列的,要想按降序排列,有3種方法。為了給大家講的更詳細一點,在第一個方法中我
用了好幾種數據類型;后面兩種方法就只用了一種數據類型,以減少篇幅。
1. sort()函數只有兩個參數時默認升序排列,在排完序后,再用reverse()函數把整個序列給翻轉一下,這樣序列就變成了降序;把上面的代碼改一下就好了
1 #include<iostream> 2 #include<vector> 3 #include<string> 4 #include<algorithm> 5 using namespace std; 6 int main() 7 { 8 int a[10]={6,5,4,8,3,9,7,10,1,2}; 9 char b[8]={'h','z','l','n','m','r','d','g'}; 10 vector<double> v1; 11 vector<string> v2; 12 v1.push_back(3.6); 13 v1.push_back(0.8); 14 v1.push_back(-0.5); 15 v1.push_back(-2.4); 16 v1.push_back(1.2); 17 v2.push_back("abcde"); 18 v2.push_back("fdbcde"); 19 v2.push_back("apcde"); 20 v2.push_back("fdbcdc"); 21 v2.push_back("fdbc"); 22 23 cout<<"對a排序前:"; 24 for(int i=0;i<10;i++) 25 cout<<a[i]<<" "; 26 cout<<"\n對a默認排序后:"; 27 sort(a+1,a+9); //可以指定任意合法的排序區間,不能越界 28 for(int i=0;i<10;i++) 29 cout<<a[i]<<" "; 30 cout<<"\n對a降序排序后:"; 31 reverse(a+1,a+9); 32 for(int i=0;i<10;i++) 33 cout<<a[i]<<" "; 34 35 cout<<"\n\n對b排序前:"; 36 for(int i=0;i<8;i++) 37 cout<<b[i]<<" "; 38 cout<<"\n對b默認排序后:"; 39 sort(b,b+8); //對整個b排序 40 for(int i=0;i<8;i++) 41 cout<<b[i]<<" "; 42 cout<<"\n對b降序排序后:"; 43 reverse(b,b+8); 44 for(int i=0;i<8;i++) 45 cout<<b[i]<<" "; 46 47 cout<<"\n\n對v1排序前:"; 48 for(int i=0;i<v1.size();i++) 49 cout<<v1[i]<<" "; 50 cout<<"\n對v1排序后:"; 51 sort(v1.begin(),v1.end()); 52 for(int i=0;i<v1.size();i++) 53 cout<<v1[i]<<" "; 54 cout<<"\n對v1默認排序后:"; 55 reverse(v1.begin(),v1.end()); 56 for(int i=0;i<v1.size();i++) 57 cout<<v1[i]<<" "; 58 59 cout<<"\n\n對v2排序前:"; 60 for(int i=0;i<v2.size();i++) 61 cout<<v2[i]<<" "; 62 cout<<"\n對v2排序后:"; 63 sort(v2.begin(),v2.end()); 64 for(int i=0;i<v2.size();i++) 65 cout<<v2[i]<<" "; 66 cout<<"\n對v2默認排序后:"; 67 reverse(v2.begin(),v2.end()); 68 for(int i=0;i<v2.size();i++) 69 cout<<v2[i]<<" "; 70 cout<<"\n"; 71 return 0; 72 }
結果如下:
可以看到,在用reverse()翻轉后就變成了降序,這里提醒一下,為了節省篇幅,讓大家看起來更流暢,下面兩個方法都將只使用一種數據類型了,以減少代碼長度
2. 除了用reverse()翻轉外,還可以借助c++標准庫來實現降序(或升序)。此時要包含頭文件<functional>,<functional>頭文件提供了一些基於模板的比較函數對象,
這里在排序的時候只用到了 greater<type>() 和 less<type>() 兩個;讓 greater<type>() 或 less<type>() 做sort()函數的第三個參數來實現升序或降序排列;其中
greater<type>() 用於降序排列,less<type>() 用於升序排列,具體用法看代碼
1 #include<iostream> 2 #include<functional> 3 #include<algorithm> 4 using namespace std; 5 int main() 6 { 7 int a[10]={6,5,4,8,3,9,7,10,1,2}; 8 9 cout<<"對a排序前:"; 10 for(int i=0;i<10;i++) 11 cout<<a[i]<<" "; 12 13 cout<<"\n對a降序排列后:"; 14 sort(a,a+10,greater<int>()); 15 for(int i=0;i<10;i++) 16 cout<<a[i]<<" "; 17 18 cout<<"\n對a升序排列后:"; 19 sort(a,a+10,less<int>()); 20 for(int i=0;i<10;i++) 21 cout<<a[i]<<" "; 22 cout<<"\n"; 23 return 0; 24 }
結果如下圖:
3. 第三個方法是自己寫一個比較函數來實現升序或降序排列,並讓這個比較函數做sort()函數的第三個參數;其實比較函數不僅能實現升序降序排列,還能實現其他的功能。
這就是sort()函數功能強大的地方,它可以擴展,而擴展的關鍵就是第三個參數,所以我把這種方法放在最后講。
先說一下比較函數吧,當你想實現特定比較方式的時候,就要自己定義一個返回bool值的比較函數了;這時sort()函數的第三個參數就是一個函數,如果它返回假值就交換
操作對象的位置,返回真值的話操作對象位置不變。下面就用比較函數來實現升序降序的排列,看代碼
1 #include<iostream> 2 #include<functional> 3 #include<algorithm> 4 using namespace std; 5 bool cmp1(int a,int b) //按降序排列 6 { 7 return a>b; 8 } 9 10 bool cmp2(int a,int b) //按升序排列 11 { 12 return a<b; 13 } 14 int main() 15 { 16 int a[10]={6,5,4,8,3,9,7,10,1,2}; 17 18 cout<<"對a排序前:"; 19 for(int i=0;i<10;i++) 20 cout<<a[i]<<" "; 21 22 cout<<"\n對a降序排列后:"; 23 sort(a,a+10,cmp1); //這里不需要對比較函數cmp1傳入參數 24 for(int i=0;i<10;i++) 25 cout<<a[i]<<" "; 26 27 cout<<"\n對a升序排列后:"; 28 sort(a,a+10,cmp2); ////不需要對比較函數cmp2傳入參數 29 for(int i=0;i<10;i++) 30 cout<<a[i]<<" "; 31 cout<<"\n"; 32 return 0; 33 }
結果看下圖:
這里對比較函數的原理介紹一下: bool cmp(int a, int b);在定義這個比較函數的時候要明確比較對象的數據類型,這里是int型,也可以是其他的任意類型,比如結構體、vector、鏈表等。
但是在使用的時候(即做sort()函數的第三個參數時)不用對cmp傳入參數,這是需要注意的地方。下面就是比較原理了
bool cmp(int a,int b)
{
return a>b;
}
sort(a,a+10,cmp);
sort() 操作的對象數組或vector中兩個挨着的順序元素分別賦值到a和b上,通過一系列操作(這個操作就是你寫的比較函數要實現的功能)后,返回bool值。
上面的sort()函數都是對簡單的數據類型進行排序,那之前也說過,sort()還可以對結構體、鏈表、vector等排序,不過還是要你自己去寫比較函數的。這里就用結構體舉例了,
下面通過一道題來體現比較函數的強大功能,這是之前我刷過的PTA的一道題。題目如下
其實這道題就要用到比較函數,用比較函數來實現sort()對結構體的排序,而且這里的比較函數要比之前寫的比較函數cmp1和cmp2復雜點,並且比較對象都是結構體。
下面只貼出了封裝的結構體和比較函數的代碼
1 struct student{ 2 int id,dscore,cscore; 3 int sum;//總分 4 }; 5 bool cmp(student a,student b) 6 { //按降序排列 7 if(a.sum!=b.sum) 8 return a.sum>b.sum; //優先按總分的高低排序 9 else if(a.dscore!=b.dscore) 10 return a.dscore>b.dscore; //總分相同則優先按德分排序 11 else 12 return a.id<b.id; //總分和德分都相同則按學號排序 13 }
本題我在 “PTA刷題” 隨筆里面詳細講到了,里面有完整代碼,想看的可以去看一下,附上鏈接:
本人還正在學習中,水平有限,如果哪里寫的不當,還請指出,謝謝哈 !