2017-07-18 8 views
3

私はコンピュータサイエンスの新人です。これはハッシュ関数と関係があると思います。誰かがクラスから整数キーを作成する方法を提案できますか?

私は、CPP内のクラスがあります。今

class Car{ 
    public: 
    int fleetId; 
    OwnershipEnum owner; 
    int buildDate; 
    bool hasFourDoors; 

    ... with many other members 
}; 

を、私の問題は、「科学的に」私はリスト4人のメンバーに基づいて、整数キーを生成する方法、ありますか?私は簡単な方法を考えることができ

10000*int(fleetId) + 1000 * int(owner) + 100×int(buildDate) + int(hasFourDoors)

私はキーが連続している理想的だと思うので、私は、アレイ内のすべての車のオブジェクトを格納し、これを直接車のオブジェクトにアクセスするための鍵を生成し使用することができます。

*****コメントあたりとして:車はすべて異なっている、

を********全く同じ車はありません*****これら四つのメンバーは静的です:彼らは勝ちました作成後に変更する*****

誰も私にここで適切な解決策を教えてもらえますか?

おかげ

+0

2つの異なる 'Car'インスタンスがsaを共有できるか私の鍵? – Bathsheba

+2

各フィールドの値の範囲が小さい場合を除き、すべてのキーが異なることを一般的に保証することはできません。ハッシュの衝突を許可する必要があります。 – Barmar

+3

キーの目的は、オブジェクトを一意に識別することです。これは、 'isGoodCondition'と' isBooked'はキーにインクルードするのに適していないことを意味します。なぜなら、これらの値は時間とともに変化するからです。車の場合、登録簿と登録日のようなものはそれを識別するのに十分なものでなければなりません。 – jsheeran

答えて

3

あなたはstd::hash使用して、それを得るための方法を構築することができます: そのちょうど簡単な例を。 2台の車(なぜなら同じフリートの一部である)同じfleetIdを有する、同じ所有者、及び双方が予約され、良好に想像:

std::size_t CarHash(const Car& car) 
{ 
    std::size_t h1 = std::hash<int>{}(car.fleetId); 
    std::size_t h2 = std::hash<int>{}(int(car.owner)); 
    std::size_t h3 = std::hash<int>{}(int(car.isGoodCondition)); 
    std::size_t h4 = std::hash<int>{}(int(car.isBooked)); 
    return h1^(h2 << 1)^(h3 << 2)^(h4 << 3); 
} 
+0

軽微な質問:それだけで十分でしょうか?それらは一意でなければならないので、オブジェクトのアドレス? –

+0

'std :: hash {}(int(car));'これを説明できますか? – yassin

+0

@yassinいいえ、それは(間違っていたので)説明がありません、それを指摘してくれてありがとう:) – Netwave

3

これらの部材の組み合わせが一意に車を識別するために十分ではありません調子。これらのプロパティに基づいて計算すると、同じIDになります。 @jsheeranの示唆しているように、ナンバープレートは一意の識別子として使用できます。

それ以外の場合は、idの別のメンバーをcarクラスに追加し、carの各コンストラクターコールでグローバルな増加キー用の静的変数を設定します。ただし、これは実装の一例に過ぎず、キーを管理するための別のクラスが必要な場合があることに注意してください。

class Car{ 

public: 
    Car() : id(++nextId) {} 

    const unsigned id; 

private: 
    static unsigned nextId; 
}; 

unsigned Car::nextId = 0U; // initialize in your cpp using the cars 

int main() 
{ 
    Car a; 
    Car b; 
    Car c; 

    std::cout << a.id << b.id << c.id; // will print 012 
} 

もう1つの提案は、GUIDを使用することです。あなたのプラットフォームや使用しているライブラリに応じて、次のような解を見つけることができます:https://msdn.microsoft.com/en-us/library/ms688568(VS.85).aspx

0

あなたが衝突のないキーを望んでおり、すべてのフィールドが範囲内の任意の値を取ると仮定しましょう。sizeof int)+ sizeof(OwnershipEnum)+すべての衝突または66ビットを防ぐための2ビットのキー。これは、許容できると考えると、このように計算することができます。

struct key { 
    int fleetId; 
    OwnershipEnum owner; 
    char bools; 

    key(Car _myCar) : 
     fleetId(_myCar.fleetId), 
     owner(_myCar.owner), 
     bools(!!_myCar.isGoodCondition & !!_myCar.isBooked << 1) 
    {} 

    bool operator ==(key other) { return fleetId == other.fleetId && owner == other.owner && bools == other.bools; } 
}; 

このようにテスト:

Car first{1, (OwnershipEnum)2, false, true}; 
    Car second{1, (OwnershipEnum)2, false, true}; 
    Car third{8, (OwnershipEnum)1, true, true}; 

    key k1{first}, k2{second}, k3{third}; 

    std::cout << (k1 == k2) << "\n"; //true 
    std::cout << (k2 == k3) << "\n"; //false 
    std::cout << (k3 == k1) << "\n"; //false 

フルプログラム例:http://cpp.sh/2vv2a

それは明らかに間違っているという仮定のですが、あなたは削減しようとすることができますfleetIdの可能なすべての値を16ビットに収めるか、OwnershipEnumを短くすることができる場合は、鍵のサイズ

関連する問題