Sobes.tech
Middle

Strukturunuzu unordered_map-da saxlamaq üçün nə etmək lazımdır?

sobes.tech Süni İntellekt

AI-dan cavab

std::unordered_map-də açar kimi strukturun quruluşunu saxlamaq üçün aşağıdakıları təmin etmək lazımdır:

  1. Hash funksiyası (hash function): Struktur nümunəsi üçün hash dəyərini tapır.
  2. Bərabərlik operatoru (operator==): İki struktur nümunəsini bərabərliyə yoxlayır.

Bu elementləri təmin etmək üçün bir neçə üsul var:

  • operator== operatorunu struktur daxilində yenidən yükləmək və std::hash-ı sizin struktur üçün ixtisaslaşdırmaq. Bu ən çox yayılmış və tövsiyə olunan yanaşmadır.

    #include <unordered_map>
    #include <string>
    #include <functional>
    
    struct MyStruct {
        int id;
        std::string name;
    
        bool operator==(const MyStruct& other) const {
            return id == other.id && name == other.name;
        }
    };
    
    // `MyStruct` üçün `std::hash`-ın ixtisaslaşdırılması
    namespace std {
        template <>
        struct hash<MyStruct> {
            size_t operator()(const MyStruct& obj) const {
                size_t h1 = hash<int>()(obj.id);
                size_t h2 = hash<std::string>()(obj.name);
                return h1 ^ (h2 << 1);
            }
        };
    }
    
    // Main funksiyasında nümunə
    int main() {
        std::unordered_map<MyStruct, int> my_map;
        MyStruct key1 = {1, "Alice"};
        MyStruct key2 = {2, "Bob"};
        MyStruct key3 = {1, "Alice"}; // eyni ilə key1
    
        my_map[key1] = 10;
        my_map[key2] = 20;
    
        if (my_map.count(key3)) {
            // my_map[key3] 10 olacaq
        }
    
        return 0;
    }
    
  • unordered_map-ı elan edərkən şablon parametrləri kimi hash və müqayisə funksiyalarını təmin etmək. Bu, struktur çox istifadə olunursa daha az əlverişlidir, çünki hər dəfə konteyner elan edərkən tipləri göstərmək lazımdır.

    #include <unordered_map>
    #include <string>
    #include <functional>
    
    struct MyStruct {
        int id;
        std::string name;
    };
    
    // Ayrı hash funksiyası
    struct MyStructHash {
        size_t operator()(const MyStruct& obj) const {
            size_t h1 = std::hash<int>()(obj.id);
            size_t h2 = std::hash<std::string>()(obj.name);
            return h1 ^ (h2 << 1);
        }
    };
    
    // Ayrı müqayisə funksiyası (və ya funktor)
    struct MyStructEqual {
        bool operator()(const MyStruct& lhs, const MyStruct& rhs) const {
            return lhs.id == rhs.id && lhs.name == rhs.name;
        }
    };
    
    // Main funksiyasında nümunə
    int main() {
        std::unordered_map<MyStruct, int, MyStructHash, MyStructEqual> my_map;
        MyStruct key1 = {1, "Alice"};
        MyStruct key2 = {2, "Bob"};
    
        my_map[key1] = 10;
        my_map[key2] = 20;
    
        return 0;
    }
    

Vacib məqamlar:

  • Hash funksiyasının düzgünlüyü: Hər hansı iki açar ab üçün, əgər a == b isə, hash(a)hash(b) eyni olmalıdır. Əks halda, hash-lar fərqli ola bilər (kolliziya).
  • Hash funksiyasının keyfiyyəti: Yaxşı hash funksiyası müxtəlif açarlar üçün bərabər paylanmış hash dəyərləri verir, kolliziyaları azaldır və performansı artırır (O(1) orta hesabla).
  • Sabitlik: Müqayisə və hash operatorları const olmalıdır, çünki onlar açar obyektini dəyişməməlidir.