對sort函數(需要algorithm頭文件),它的cmp可以是“函數”,也可以是“對象”
bool myfunction (int i,int j) { return (i<j); } struct myclass { bool operator() (int i,int j) { return (i<j);} } myobject; int main () { int myints[] = {32,71,12,45,26,80,53,33}; vector<int> myvector (myints, myints+8);//放進容器vector sort(myfunction); //參數cmp是個函數 sort(myobject);//參數cmp是個結構體對象 return 0; }
▲注意:這里的函數myfunction返回類型為bool,返回真時認為i<j,假時認為i>=j,排序默認從小到大,因此反向排序只需把return (i<j)改成return (i>j)。
另外值得一提,結構體的bool operator() (int i,int j)函數,實際上是操作符的重載函數,對括號進行了重載,相當於平時用的operator +(…)這種,因此對於結構體對象myobject,可以這樣操作bool re = myobject(1,2);,結果將會返回false,書寫的形式跟函數一樣(方便理解記憶,實際上參數並不能從“函數”類型轉換成“對象”類型,是重載)
對qsort函數,cmp是函數名
int values[] = { 40, 10, 100, 90, 20, 25 }; int cmp(const void * a, const void * b) { return ( *(int*)a - *(int*)b ); } int main () { int n; qsort (values, 6, sizeof(int), cmp);//qsort() 函數的聲明: //C 庫函數 void qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, const void*)) 對數組進行排序。 //base -- 指向要排序的數組的第一個元素的指針。 //nitems -- 由 base 指向的數組中元素的個數。 //size -- 數組中每個元素的大小,以字節為單位。 //compar -- 用來比較兩個元素的函數。 return 0; }
▲注意:這里的函數cmp必須對上原型 int (__cdecl* _PtFuncCompare)(void const, void const),說白了就是返回值為 int,函數名字隨意,函數參數類型要為 void const*(const順序可調)。里面 *(int*)a實際就是:先把 void* 型的指針a強制轉成 int* 指針,用 * ((int*)a)把指向對象拿出來比較,如果是其他float/double,不用多說,改成 *(double *)之類的。
順帶一題,此處為升序排列,返回值小於0(一般寫成返回-1),認為a比b小,等於0認為相等,大於0(一般寫成返回1)認為a比b大,想要從大到小的降序排序,改下即可
cmp( (void *) & a, (void *) & b ); | |
cmp 函數的返回值 | 描述 |
<0 | a將被排在b前面 |
>0 | a將被排在b后面 |
=0 | a=b |
對STL容器,如優先隊列(最大/最小堆,默認為最大堆)priority_queue類來說,其模板參數只能類/結構體名,因此它的"cmp"要為結構體名(注意不是上面說的myobject了,是結構體的名字),里面需有操作符()重載函數。
struct cmp //名字自定 { bool operator ()(int a, int b) { return a.val < b.val; } } int main() { /*需要頭文件queue,第一個模板參數為數據類型,第二個為容器類型,第三個為結構體*/ priority_queue<int, vector<int>, cmp> t; return 0; }
▲注意:這里的cmp返回值為bool型,函數為對括號的重載函數。
值得一提的是,這個花樣還挺多的:
class A { int val; bool operator <(int a, int b) const {return a<b;} //這里const不能省,參數你可寫成const int &a等,加const說明函數是不能改變類中的成員變量的。 //如果想最小堆優先,則將return a<b;改為return a>b;后者根據題目需求自己定義。 //friend bool operator <(const int &a, const int &b) //友元函數也可以 } int main() { priority_queue< A , vector<A> > t; return 0; }
如果類中重載了“ < ” (注意:重載 “>” 會編譯錯誤,從數學上來講只重載 < 就夠了),就不用指定隊列使用哪個cmp。若指定為最大堆可以第三參數( cmp 的位置)可寫成 less,最小堆可以寫成 greater,一步到位。
簡單來說,STL 中模板參數需要填類名,要么類里重載 '< '、要么類外寫個結構體重載 ‘()’ 后作模板參數填進去。