c++排序相關的參數“cmp“的用法及理解


對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 中模板參數需要填類名,要么類里重載 '< '、要么類外寫個結構體重載 ‘()’ 后作模板參數填進去。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM