C++
 Computer >> コンピューター >  >> プログラミング >> C++

C++でpairをキーとするunordered_mapを作成する方法

このチュートリアルでは、C++でpair(ペア)をキーとするunordered_mapを作成する方法について詳しく解説します。

unordered_mapは、デフォルトではpair型に対するハッシュ関数を提供していません。そのため、pairをキーとして使用したい場合は、カスタムハッシュ関数を明示的に指定する必要があります。

カスタムハッシュ関数の実装例

以下のコードでは、hash_pairという構造体を定義し、unordered_mapのテンプレート引数として渡しています。

#include <bits/stdc++.h>
using namespace std;
// 任意のpairに対するハッシュ値を計算する
struct hash_pair {
    template <class T1, class T2>
    size_t operator()(const pair<T1, T2>& p) const{
        auto hash1 = hash<T1>{}(p.first);
        auto hash2 = hash<T2>{}(p.second);
        return hash1 ^ hash2;
    }
};
int main(){
    // ハッシュ関数を明示的に指定
    unordered_map<pair<int, int>, bool, hash_pair> um;
    // キーとして使用するpairを作成
    pair<int, int> p1(1000, 2000);
    pair<int, int> p2(2000, 3000);
    pair<int, int> p3(2005, 3005);
    um[p1] = true;
    um[p2] = false;
    um[p3] = true;
    cout << "Contents of the unordered_map : \n";
    for (auto p : um)
        cout << "[" << (p.first).first << ", " << (p.first).second << "] ==> " << p.second << "\n";
    return 0;
}

実行結果

Contents of the unordered_map :
[1000, 2000] ==> 1
[2005, 3005] ==> 1
[2000, 3000] ==> 0

コードの解説

1. カスタムハッシュ関数の定義

hash_pair構造体では、関数呼び出し演算子operator()をオーバーロードしています。内部では、pairのfirstとsecondそれぞれに対して標準のstd::hashを適用し、得られた2つのハッシュ値をXOR演算子(^)で組み合わせています。テンプレートを使用しているため、int以外の型の組み合わせにも対応できます。

2. unordered_mapの宣言方法

unordered_mapは3つのテンプレート引数を受け取ります。第1引数がキーの型(pair<int, int>)、第2引数が値の型(bool)、第3引数がハッシュ関数(hash_pair)です。この第3引数にカスタムハッシュを指定することで、pairをキーとして扱えるようになります。

注意点:ハッシュ衝突への対策

単純なXORによるハッシュ結合は、(a, b)と(b, a)が同一のハッシュ値になるなど、衝突が発生しやすいという弱点があります。実務で利用する場合は、以下のようにビットシフトと定数を組み合わせたboost::hash_combine風の手法を採用すると、より分散性の高いハッシュになります。

size_t seed = hash1 + 0x9e3779b9;
seed ^= hash2 + 0x9e3779b9 + (seed << 6) + (seed >> 2);
return seed;

このようにカスタムハッシュ関数を用意することで、C++のunordered_mapでもpairを自由にキーとして扱うことが可能になります。

  1. C++で合計が2の累乗となるペアの数を求める方法

    配列が与えられたとき、要素の合計が2の累乗(1, 2, 4, 8, 16, ...)になるペアの個数を求める問題を解説します。まずは具体例を見てみましょう。例入力arr = [1, 2, 3]出力1この配列では、合計が2の累乗になるペアは1つだけです。該当するのは (1, 3) のペアで、合計が4になります。アルゴリズム解法の流れは以下のとおりです。配列をランダムな数値で初期化します。カウント用の変数を0で初期化します。二重ループを使って、配列内のすべてのペアを列挙します。各ペアの合計値を計算します。ビットAND演算(&)を使って、合計が2の累乗かどうかを判定します。合計が2の累乗であ

  2. C++とOpenCVでバイナリ画像(二値画像)を作成する方法を解説

    バイナリ画像(二値画像)とは、黒と白の2色のみで表現されるデジタル画像のことです。画像処理の観点から見ると、バイナリ画像は「0」と「1」という2つの値しか持たないピクセルで構成されています。ピクセルの値が0の場合は純粋な黒を、値が1の場合は純粋な白を表します。グレースケール画像では、各ピクセルが256段階の異なる値を持つのに対し、バイナリ画像では2つの値しか存在しません。このシンプルさゆえに、バイナリ画像はさまざまな用途で活用されています。例えば、モルフォロジー変換(形態学的処理)ではバイナリ画像が必要であり、背景から物体の形状を抽出する処理にもバイナリ画像が用いられます。OpenCVを使用す