天天看點

STL中排序函數的用法(Qsort,Sort,Stable_sort,Partial_sort,List::sort)QsortSortStable_sortPartial_sortList::sort

都知道排序很重要,也學了各式各樣的排序算法,冒泡、插入、歸并等等,但其實在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=