C++ priority_queue は比較関数をどのようにカスタマイズしますか? sort のカスタム比較関数との違いは何ですか?

1. C++のpriority_queueの比較関数のカスタマイズ方法とsortのカスタム比較関数との違い

まず、公式 C++ ドキュメントの priority_queue のテンプレート定義を確認してください。

template<
    class T,
    class Container = std::vector<T>,
    class Compare = std::less<typename Container::value_type>
> class priority_queue;

知らせ:

  1. 最後の 2 つのパラメータはデフォルト値があるため記述する必要はありませんが、パラメータを記述する場合は両方を記述し、順番に入力する必要があります
  2. 比較するのはクラス名です! オブジェクト名ではありません!
    アルゴリズムには、sort などのカスタム比較関数を使用する関数も多数あります。
template <class RandomAccessIterator, class Compare>  void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);

ここで渡す必要があるのはクラス名だけではなく、オブジェクト名です。
C++ の他の内部順序データ構造 (map や set など) に注目すると、これらの比較はクラス オブジェクトではなくクラス名であることがわかります。これは非常に起こりやすい間違いです。
地図:

template<
    class Key,
    class T,
    class Compare = std::less<Key>,
    class Allocator = std::allocator<std::pair<const Key, T>>
> class map;

設定:

template<
    class Key,
    class Compare = std::less<Key>,
    class Allocator = std::allocator<Key>
> class set;

要約:最も重要なことは、sort の比較関数はオブジェクトである必要があり、priority_queue などはクラス名であることです

2. 比較関数は次のとおりです。

注:構造体の関数の後に const 修飾子を追加するのが最善です。そうしないと、priority_queue! などのオブジェクトを構築するときにエラーが報告される可能性があります。
可能であれば、次のエラーが発生します。

Visual Studio コンパイラ エラー C3848 タイプ 'type' の式では、
'function' を呼び出すための const-volatile 修飾子が失われます

解決策は、以下の最初のタイプのコードのように、関数呼び出し演算子をオーバーロードするときに const 修飾子を追加することです。

vector<pair<int, int>> vec;

1 つ目: 関数オブジェクトの使用 関数オブジェクトとは何かについては、「C++ 関数オブジェクト (関数オブジェクト) とは何ですか?」を参照してください。

结构体
struct compare {
    
    
	bool operator () (const pair<int, int>& A. const pair<int, int>& B) const {
    
    
		return A.second < B.second;
    }
}
sort(vec.begin(), vec.end(), compare{
    
    });
sort(vec.begin(), vec.end(), compare());

2 番目のタイプ: グローバル関数を使用します。ここで変換する必要があります。cmp は関数ポインターであり、関数オブジェクトが実際に使用されます。ここで呼び出されるのは実際の関数オブジェクトであるため、直接
渡すことができます (追加のコンストラクターはありません)オブジェクト)。


函数
bool cmp(const pair<int, int>& A. const pair<int, int>& B) {
    
    
	return A.second < B.second;
}
sort(vec.begin(), vec.end(), cmp);
// 不用加()

3 番目の方法: 標準ライブラリに付属する小さいか大きいものを使用します。このメソッドは特定のオブジェクトも渡す必要があることに注意してください。次の 2 つのメソッドを使用できます。

less或者greater
sort(vec.begin(), vec.end(), less<pair<int, int>>()); 
sort(vec.begin(), vec.end(), less<pair<int, int>>{
    
    }); 

公式ドキュメントでも、実際には演算子 () のオーバーロードが少ないことがわかります。

std::less::operator()
bool operator()( const T& lhs, const T& rhs ) const;

したがって、less<pair<int, int>>{} はクラスのオブジェクトを構築することであり、less<pair<int, int>>() はless<pair<int, int を直接呼び出す必要があると思います。 () メソッドですが、前者はオーバーロードされた () メソッドも呼び出します。次のように
構造 (つまり、最初のメソッド) を確認できます。

结构体
struct compare {
    
    
	bool operator () (const pair<int, int>& A. const pair<int, int>& B) const {
    
    
		cout <<  "()" << endl;
		return A.second < B.second;
    }
}
sort(vec.begin(), vec.end(), compare{
    
    });
sort(vec.begin(), vec.end(), compare());

どちらのメソッドも () を出力することがわかり、比較プロセス中にオーバーロードされた () 関数が呼び出されることを示しています。

参考文献:

cppリファレンス

おすすめ

転載: blog.csdn.net/Sansipi/article/details/127858218