質問を書いていると、ソート比較関数を自分で書かなければならないことがよくありますが、比較関数の書き方が分からなければ、アルゴリズムのロジックが分かっていても問題を解くことはできません。いくつかのカスタム比較方法があります。
前提条件
- C++sort はアルゴリズム パッケージに含まれていることに注意してください。インクルード パッケージに注意してください。
- ソートのテンプレートは以下のとおりです。RandomAccessIterator はソートのみが可能であることに注意してください。!RandomAccessIteratorとは何ですか? 詳細な説明が必要な場合は、「RandomAccessIterator cppreference 」を参照してください。簡単に言えば、これは任意のオフセットでアクセスできる反復子です。これがサポートされていない場合、並べ替えに sort を使用することはできません。
ランダム アクセス イテレータは、要素が指す要素に対して任意のオフセット位置にある要素にアクセスするために使用できるイテレータであり、ポインタと同じ機能を提供します。
-
たとえば、マップ内のイテレータは双方向イテレータであり、イテレータ ++ のみをサポートします。 - - は +n などの任意のオフセットをサポートしないため、ソートはソートに使用できません。
-
Vector、DEQUE のサポート RandomAccessIterator、list、map、multimap、set、multiset は双方向イテレータのみをサポートします。
使用法
std::sort
default (1)
template <class RandomAccessIterator> void sort (RandomAccessIterator first, RandomAccessIterator last);
custom (2)
template <class RandomAccessIterator, class Compare> void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);
つまり、非書き込み比較機能を使用する場合と、比較機能をカスタマイズする場合の2種類があります。
注: 最初の 2 つのパラメータがどのような種類であっても、RandomAccessIterator です。つまり、変数を直接渡すことはできず、対応するイテレータを渡す必要があります。これは初心者が最初に犯しやすい間違いです。
範囲内の 2 つの要素を引数として受け取り、bool に変換可能な値を返すバイナリ関数。返される値は、最初の引数として渡された要素が、それが定義する特定の厳密な弱い順序付けにおいて 2 番目の引数より前に来るとみなされるかどうかを示します。
関数は引数を変更してはなりません。これは関数ポインターまたは関数オブジェクト
のいずれかです。
タイプ 1: 比較関数を直接記述する
bool myfunction (int i,int j) {
return (i<j); }
注: この比較関数は、クラス (グローバル領域) の外部に書き込むか、静的関数として宣言する必要があります。(メンバ関数の場合、デフォルトで this ポインタを持つため、sort 関数が必要とする関数オブジェクトの型とは異なるためだと聞きました。)
タイプ 2: 構造体を定義し、関数オブジェクト (関数オブジェクト) を構築します。これは、演算子 () をオーバーロードします。これは、関数オブジェクトを構築するのと同等です。
struct myclass {
bool operator() (int i,int j) {
return (i<j);}
} myobject;
タイプ 3: ラムバダ関数を使用する
単純な関数比較には、 C++11 の新機能 lambada 関数を使用できます。
sort(msVector.begin(), msVector.end(), [](const MyStruct& ms1, const MyStruct& ms2){
return ms1.weight < ms2.weight;
});
参照できます: https://www.cnblogs.com/DswCnblog/p/5629165.html
タイプ 4: デフォルトの値を小さくして使用します。
実際、less と great はどちらも関数オブジェクト、つまりFunctionオブジェクト です。
一般に、関数オブジェクトは、メンバー関数 Operator() が定義されたクラスのインスタンスです。このメンバー関数を使用すると、オブジェクトを関数呼び出しと同じ構文で使用できるようになります。
less テンプレートを見てみましょう。
template <class T> struct less {
bool operator() (const T& x, const T& y) const {
return x<y;}
typedef T first_argument_type;
typedef T second_argument_type;
typedef bool result_type;
};
less は実際に () 演算子をオーバーロードしていることがわかります。less は、最初の要素が 2 番目の要素より小さいことを意味し、実際には昇順であることに注意してください。
例:
// less example
#include <iostream> // std::cout
#include <functional> // std::less
#include <algorithm> // std::sort, std::includes
int main () {
int foo[]={
10,20,5,15,25};
int bar[]={
15,10,20};
std::sort (foo, foo+5, std::less<int>()); // 5 10 15 20 25
std::sort (bar, bar+3, std::less<int>()); // 10 15 20
if (std::includes (foo, foo+5, bar, bar+3, std::less<int>()))
std::cout << "foo includes bar.\n";
return 0;
}
同様に、大きいとは降順を意味します。これは彼のテンプレートとアプリケーションの例です。
レンプレート:
template <class T> struct greater {
bool operator() (const T& x, const T& y) const {
return x>y;}
typedef T first_argument_type;
typedef T second_argument_type;
typedef bool result_type;
};
例:
// greater example
#include <iostream> // std::cout
#include <functional> // std::greater
#include <algorithm> // std::sort
int main () {
int numbers[]={
20,40,50,10,30};
std::sort (numbers, numbers+5, std::greater<int>());
for (int i=0; i<5; i++)
std::cout << numbers[i] << ' ';
std::cout << '\n';
return 0;
}
個人的には、比較的直感的な 1 番目、2 番目、および 4 番目の方法を使用することをお勧めします。他の方法がある場合は、ご相談ください。