C/C++中有一個快速排序的標準庫函數 qsort ,在stdlib.h 中聲明,其原型為:
void qsort(void *base, int nelem, unsigned int width, int ( * pfCompare)( const void *, const void *));
使用該函數,可以對任何類型的一維數組排序。該函數參數中,base 是待排序數組的起始地址,nelem 是待排序數組的元素個數,width 是待排序數組的每個元素的大小(以位元組為單位),最後一個參數 pfCompare 是一個函數指標,它指向一個“比較函數”。排序就是一個不斷比較並交換位置的過程。qsort 如何在連元素的類型是什麼都不知道的情況下,比較兩個元素並判斷哪個應該在前呢?答案是,qsort 函數在執行期間,會通過pfCompare指標調用一個 “比較函數”,用以判斷兩個元素哪個更應該排在前面。這個“比較函數”不是C/C++的庫函數,而是由使用qsort 的程式員編寫的。在調用qsort 時, 將“比較函數”的名字作為實參傳遞給pfCompare。程式員當然清楚該按什麼規則決定哪個元素應該在前,哪個元素應該在後,這個規則就體現在“比較函數”中。
qsort 函數的用法規定,“比較函數”的原型應是:int 函數名(const void * elem1, const void * elem2);該函數的兩個參數,elem1 和elem2,指向待比較的兩個元素。也就是說, * elem1 和* elem2 就是待比較的兩個元素。該函數必須具有以下行為:
1) 如果 * elem1 應該排在 * elem2 前面,則函數傳回值是負整數(任何負整數都行)。
2) 如果 * elem1 和* elem2 哪個排在前面都行,那麼函數返回0
3) 如果 * elem1 應該排在 * elem2 後面,則函數傳回值是正整數(任何正整數都行)。
例如:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
int compare(const void *a, const void *b)
{
int *pa = (int*)a;
int *pb = (int*)b;
return (*pa )- (*pb); //從小到大排序
}
void main()
{
int a[10] = {5, 6, 4, 3, 7, 0 ,8, 9, 2, 1};
qsort(a, 10, sizeof(int), compare);
for (int i = 0; i < 10; i++)
cout << a[i] << " " << endl;
}
再如:
下面的程式,功能是調用qsort 庫函數,將一個unsigned int 數組按照個位元從小到大進行排序。比如 8,23,15 三個數,按個位元從小到大排序,就應該是 23,15,8:
#include <stdio.h>
#include <stdlib.h>
int MyCompare( const void * elem1, const void * elem2
{
unsigned int * p1, * p2;
p1 = (unsigned int *) elem1; //語句6
p2 = (unsigned int *) elem2; //語句7
return (* p1 % 10) - (* p2 % 10 ); //語句8
}
#define NUM 5
int main()
{
unsigned int an[NUM] = { 8,123,11,10,4 };
qsort( an, NUM, sizeof(unsigned int), MyCompare);
for( int i = 0;i < NUM; i ++ )
printf("%d ", an[i]);
return 0;
}
上面程式的輸出結果是:
10 11 123 4 8
qsort 函數執行期間,需要比較兩個元素哪個應在前面時,就以兩個元素的地址作為參數,調用 MyCompare 函數。如果傳回值小於0,則qsort 就得知第一個元素應該在前,如果傳回值大於0,則第一個元素應該在後。如果傳回值等於0,則哪個在前都行。
對語句6 解釋如下:由於elem1 是 const void * 類型的,是void 指標,那麼運算式“*elem1”是沒有意義的。elem1 應指向待比較的元素,即一個unsigned int 類型的變數,所以要經過強制類型轉換,將elem1 裡存放的地址賦值給 p1,這樣,* p1 就是待比較的第
一個元素了。語句7 同理。語句8 體現了排序的規則。如果 *p1 的個位元小於 *p2 的個位元,那麼就返回負值。其他兩種情況不再贅述。