都知道排序很重要,也學了各式各樣的排序算法,冒泡、插入、歸并等等,但其實在ACM比賽中,隻要不是太慢的算法,都可以适用(除非某些題目卡時間卡的很死),這個時候,速度與技巧便成了關鍵,而在C++的标準庫中,就已經定義好了一些排序函數,下面來一一介紹它們吧=7=
Qsort
函數原型為void qsort(void*base,size_t num,size_t width,int(__cdecl*compare)(const void*,const void*));包含四個參數,分别是待排序數組首位址、數組中待排序元素數量、各元素的占用空間大小、指向函數的指針(就是自己的排序函數),這個函數在C語言中就可以使用了,可以不包含第四個參數進行對數組的排序,此時系統會自動按照從小到大的排序,例如:
int a[] = {4,1,2,3,5,7,6};
qsort(a,7,sizeof(a[0]));
//結果:1 2 3 4 5 6 7
好,那麼qsort如何對結構體進行排序呢,我們知道,對結構體數組的排序需要自己寫一個排序函數,但是和其他函數不一樣的是,qsort的排序函數有其固定的形式,例如:
struct node{
int id,num;
}a[6] = {{1,3},{2,4},{3,1},{4,2},{5,6},{6,5}};
int cmp(const void *a,const void *b){
node *aa = (node *)a;
node *bb = (node *)b;
if(aa->num == bb->num){
return aa->id < bb->id;
}
return aa->num > bb->num; //按num值升序排序
}
qsort(a,6,sizeof(a[0]),cmp);
可以看到,cmp函數形參不能直接定義為相應類型,隻能定義為const void *p 類型,然後強制轉換為相應類型再做出處理。真是因為如此,我們在ACM中不會太經常也不建議用qsort函數,但還是得明白一下操作。
Sort
這個函數相信大家都很熟悉了,就是常用排序函數,給給定區間内進行排序,時間複雜度為O(N*logN),參數有三個,分别是首位址、末位址和排序函數,第三個參數省略時按照從小到大排序,例如:
1 int a[] = {4,1,2,3,5,6};
2 sort(a,a+6);
3
4 //排序結果: 1 2 3 4 5 6
稍微難一點的就是對結構體數組進行排序,此時,sort函數就有多種選擇方式了,可以在結構體内重載操作符,寫比較函數或者仿函數等都可以,例如:
1 struct node{
2 int id,num;
3
4 //重載比較符
5 bool operator < (const node &b) const{
6 if(num == b.num){
7 return id < b.id;
8 }
9 return num > b.num;
10 }
11 }a[6] = {{1,3},{2,4},{3,1},{4,2},{5,6},{6,5}};
12
13
14 //編寫比較函數
15 int cmp(node &a,node &b){
16 if(a.num == b.num){
17 return a.id < b.id;
18 }
19 return a.num > b.num;
20 }
21
22 sort(a,a+6); //重載比較符
23 sort(a,a+6,cmp); //編寫比較函數
不使用結構體,使用仿函數就是:
1 //編寫仿函數
2 class CMP{
3 public:
4 CMP(int _id,int _num):id(_id),num(_num){}
5 int id;
6 int num;
7 bool operator < (const node &b) const{
8 if(num == b.num){
9 return id < b.id;
10 }
11 return num > b.num;
12 }
13 };
14
15 vector<CMP>a;
16 sort(a,a+6);
基本上Sort的操作就是這些了。
Stable_sort
其實你會發現不僅僅sort有stable_sort,partition也有stable_partition,我們都知道sort是一個不穩定的排序,但stable_sort就是如字面意思一樣,是一個穩定的sort排序,那麼你可能有疑問,排序後,相同的元素會在一起,穩定不穩定不都是一樣的麼,如果你存在這個疑問的話,那就肯定還是做題力度不夠=7=,你隻想到了對元素表面的排序,如果是對元素的某種性質排序呢,例如:
1 string s[4] = {"spring","lip","eye","winter"};
2
3 bool cmp(string a, string b){
4 return a.size() < b.size();
5 }
6
7 sort(s,s+4,cmp);
對于這段代碼,"lip"和"eye"對于比較函數來說是相等的,是以排序後結果可能lip在eye的前面也可能在eye後面,但是如果這裡使用stable_sort,排序前lip在eye前面,不管排序次數如何,lip一定會排在eye的前面。
其他用法和sort一樣。
Partial_sort
和字面意思一樣,部分排序,函數有三個參數,分别是區間要排序的首位置、要排序的末位置以及區間末位置,函數的作用就是把區間内前n個元素排序,其他元素則依次排在末尾,例如:
int a[] = {6,5,4,3,2,1};
partial_sort(a,a+3,a+6);
//排序結果: 1 2 3 6 5 4
函數其他用法和sort相同,也就沒什麼好講的=7=
List::sort
這個是list容器中專有的排序函數,直接對疊代器操作,使用方式為:
1 list<int>a;
2 a.sort();
那麼全部的排序函數已經講完了,如果在之前你隻知道一個sort或者qsort的話,是不是突然覺得知道了很多新東西呢,其實STL的東西遠不止這些,學好了STL,對于我們做題真的是有質和速度的雙從提升。
還有就是文中提及的仿函數,這個東西也是STL裡面的一大類,會專門将這個的,嘻嘻。
後記:有人和我說nth_element函數的講解,但是nth_element并不算是排序函數,是以沒有寫在這裡,都會寫的=7=