1. 程式人生 > >淺談C++中qsort與sort的使用方法與區別

淺談C++中qsort與sort的使用方法與區別

這兩天在刷leetcode時看到了一些關於排序的題目,其中遇到各種大神對sort與qsort的使用,個人在使用時對比發現了一些sort與qsort的區別,並對它們的使用方法進行了一些總結介紹。

在平時程式設計時,排序是一種經常要用到的操作。如果每次都自己臨場寫)排序演算法,不僅容易出錯,而且浪費寶貴的時間。在C++的STL裡面有兩個sort與qsort可以直接用於對各種型別的資料以及容器進行排序。

1、qsort

qsort函式定義在標頭檔案<algorithm>中,使用時需要include該標頭檔案

功 能: 使用快速排序例程進行排序   

用 法: void qsort(void *base, int nelem, int width, int (*fcmp)(const void *,const void *));    
引數:1、待排序陣列首地址; 2、陣列中待排序元素數量; 3、各元素的佔用空間大小; 4、指向函式的指標,用於確定排序的順序 
比如:對一個長為1000的陣列進行排序時,int a[1000]; 那麼base應為a,num應為 1000,width應為 sizeof(int),cmp函式隨自己的命名。

使用方法:

void qsort( void *base, size_t num, size_t width, int (__cdecl *compare ) 
int compare (const void *elem1, const void *elem2 ) );

qsort(quicksort)主要根據你給的比較條件給一個快速排序,主要是通過指標移動實現排序功能。排序之後的結果仍然放在原來陣列中。

引數意義如下:

base:需要排序的目標陣列開始地址 
num:目標陣列元素個數 
width:目標陣列中每一個元素長度 
compare:函式指標,指向比較函式(這個函式是要自己寫的,sort中預設升序)

(1)對int型別陣列排序 
int num[100]; 
int cmp ( const void *a , const void *b ) 

return *(int *)a - *(int *)b; 
}

可見:引數列表是兩個空指標,現在他要去指向你的陣列元素。所以轉型為你當前的型別,然後取值。升序排列。

qsort(num,100,sizeof(num[0]),cmp);

(2)對char型別陣列排序(同int型別)

 char word[100];

int cmp( const void *a , const void *b )

{

return *(char *)a - *(int *)b;

}

qsort(word,100,sizeof(word[0]),cmp);


(3)對double型別陣列排序(特別要注意)

double in[100];

int cmp( const void *a , const void *b ) 

return *(double *)a > *(double *)b ? 1 : -1; 
}
返回值的問題,顯然cmp返回的是一個整型,所以避免double返回小數而被丟失。  
qsort(in,100,sizeof(in[0]),cmp);

(4)對結構體一級排序

struct In 

double data; 
int other; 
}s[100]

//按照data的值從小到大將結構體排序,關於結構體內的排序關鍵資料data的型別可以很多種,參考上面的例子寫 
int cmp( const void *a ,const void *b) 

return (*(In *)a).data > (*(In *)b).data ? 1 : -1; 

qsort(s,100,sizeof(s[0]),cmp);

(5)對結構體二級排序

struct In 

int x; 
int y; 
}s[100];

//按照x從小到大排序,當x相等時按照y從大到小排序 
int cmp( const void *a , const void *b ) 

struct In *c = (In *)a; 
struct In *d = (In *)b; 
if(c->x != d->x) return c->x - d->x; 
else return d->y - c->y; 

qsort(s,100,sizeof(s[0]),cmp);

(6)對字串進行排序 
char str[100][100]; 
int cmp(const void* a,const void* b )

{

return strcmp((char *)a,(char*)b);

}

qsort(str,n,sizeof(str[0]),cmp);

struct In 

int data;
char str[100]; 
}s[100];

//按照結構體中字串str的字典順序排序 
int cmp ( const void *a , const void *b ) 

return strcmp( (*(In *)a)->str , (*(In *)b)->str ); 

qsort(s,100,sizeof(s[0]),cmp);

使用qsort一個比較麻煩的地方在於需要自己編寫compare即比較函式,而sort預設為升序排序,在大多數情況下,使用sort會更方便一些。

2、sort

sort函式,與qsort同為排序函式,複雜度為n*log2(n)。sort()定義在標頭檔案<algorithm>中。sort函式是標準模板庫的函式,已知開始和結束的地址即可進行排序,可以用於比較任何容器(必須滿足隨機迭代器),任何元素,任何條件,執行速度一般比qsort要快。另外,sort()是類屬函式,可以用於比較任何容器,任何元素,任何條件。 
注意:預設是升序排序。


sort 使用時得註明:using namespace std; 或直接打 std::sort() 還得加上 #include<algorithm>

例: 
#include<iostream> 
#include<algorithm> 
using namespace std; 
int main()

int a[20]; 
for(int i=0;i<20;++i) 
cin>>a[i]; 
sort(a,a+20); //範圍,很明顯這裡是a+20 注意,這是必要的,如果是a+19 
for(i=0;i<20;i++) //最後一個值a[19]就不會參與排序。 
cout<<a[i]<<endl; 
return 0; 
}

sort是qsort的升級版,如果能用sort儘量用sort,使用也比較簡單,不像qsort還得自己去寫 cmp 函式,只要註明 使用的庫函式就可以使用,引數只有兩個(如果是普通用法)頭指標和尾指標; 
預設sort排序後是升序,如果想讓他降序排列,可以使用自己編的cmp函式 
bool compare(int a,int b) 

return a>b; //www.cdtarena.com降序排列,如果改為return a<b,則為升序


sort(*a,*b,cmp);

例子:
#include<iostream>
#include<algorithm>
using namespace std;
bool cmp (const int a, const int b)
{
    return a > b;
}
int main()
{
    int data[5];
    for(int i = 0; i < 5; i++)
        cin >> data[i];
    sort(data, data + 5, cmp);
    return 0;
}

sort函式可以傳兩個引數或三個引數。第一個引數是要排序的區間首地址,第二個引數是區間尾地址的下一地址。也就是說,排序的區間是[a,b)。簡單來說,有一個數組int a[100],要對從a[0]到a[99]的元素進行排序,只要寫sort(a,a+100)就行了,預設的排序方式是升序。 排序的資料型別不侷限於整數,只要是定義了小於運算的型別都可以,比如字串類string。如果是沒有定義小於運算的資料型別,或者想改變排序的順序,就要用到第三引數——比較函式。比較函式是一個自己定義的函式,返回值是bool型,它規定了什麼樣的關係才是“小於”。想把剛才的整數陣列按降序排列,可以先定義一個比較函式cmp: 
bool cmp(int a,int b)
{
    return a>b;
}

排序的時候就寫sort(a,a+100,cmp); 
假設自己定義了一個結構體node: 
struct node{
    int a;
    int b;
    double c;
}; 
有一個node型別的陣列node arr[100],想對它進行排序:先按a值升序排列,如果a值相同,再按b值降序排列,如果b還相同,就按c降序排列。就可以寫這樣一個比較函式: 
以下是程式碼片段: 
bool cmp(node x,node y)
{
     if(x.a!=y.a)  return x.a
     if(x.b!=y.b)  return x.b>y.b;
     return  return x.c>y.c;

排序時寫sort(arr,a+100,cmp); 


3、sort與qsort的對比

(1)最直觀的差別,函式形式不一樣,

qsort的使用方式為:

void qsort( void *base, size_t num, size_t width, int (__cdecl *compare ) 

sort的使用方式為:

template<classRandomAccessIterator>

voidsort ( RandomAccessIterator first, RandomAccessIterator last );

template<classRandomAccessIterator, classCompare>

voidsort ( RandomAccessIterator first, RandomAccessIterator last, Compare comp );

sort有二個引數與三個引數版本,兩個引數預設升序排序,第三個引數可用於指定比較函式,調整排序方式。

(2)compare函式的寫法也是不一樣的。

qsort的compare函式寫法為:

int compare (const void *elem1, const void *elem2 ) );

sort的compare函式返回的是bool值;

(3)sort是一個改進版的qsort. std::sort函式優於qsort的一些特點:對大陣列採取9項取樣,更完全的三路劃分演算法,更細緻的對不同陣列大小採用不同方法排序。如果能用sort儘量用sort,使用也比較簡單,不像qsort還得自己去寫 cmp 函式,只要註明 使用的庫函式就可以使用,引數只有兩個(如果是普通用法)頭指標和尾指標;預設sort排序後是升序,如果想讓他降序排列,可以使用自己編的cmp函式