Sobes.tech
Middle

Түзүмүңүздү unordered_mapта сактоо үчүн эмне кылуу керек?

sobes.tech AI

AIден жооп

std::unordered_map ичинде структураны ачкыч катары сактоо үчүн, төмөнкүлөрдү камсыз кылуу керек:

  1. Хеш-функция (hash function): Структуранын үлгүсү үчүн хеш маанисин табат.
  2. Теңдик оператору (operator==): Эки структура үлгүсүн теңдештирет.

Бул элементтерди камсыз кылуу үчүн бир нече жол бар:

  • operator== операторун структуранын ичинде кайра жүктөө жана std::hashти сиздин структураңыз үчүн атайын кылуу. Бул эң кеңири колдонулган жана сунушталган ыкма.

    #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` үчүн `std::hash` атайын кылуу
    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 ичинде мисал
    int main() {
        std::unordered_map<MyStruct, int> my_map;
        MyStruct key1 = {1, "Alice"};
        MyStruct key2 = {2, "Bob"};
        MyStruct key3 = {1, "Alice"}; // эквиваленттүү key1
    
        my_map[key1] = 10;
        my_map[key2] = 20;
    
        if (my_map.count(key3)) {
            // my_map[key3] 10 болот
        }
    
        return 0;
    }
    
  • unordered_mapти жарыялоо учурунда хеш жана салыштыруу функцияларын шаблон параметрлери катары берүү. Бул көбүрөөк ыңгайсыз, эгер сиз структураны көп колдонуп жатсаңыз, анткени ар бир жарыялоо сайын салыштыруу жана хешердин түрлөрүн көрсөтүшүңүз керек.

    #include <unordered_map>
    #include <string>
    #include <functional>
    
    struct MyStruct {
        int id;
        std::string name;
    };
    
    // Ажыратылган хеш функциясы
    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);
        }
    };
    
    // Ажыратылган салыштыруу функциясы (же функтор)
    struct MyStructEqual {
        bool operator()(const MyStruct& lhs, const MyStruct& rhs) const {
            return lhs.id == rhs.id && lhs.name == rhs.name;
        }
    };
    
    // Main ичинде мисал
    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;
    }
    

Мөөнөттүү маанилүү:

  • Хеш-функциянын тууралыгы: Ар бир эки ачкыч a жана b үчүн, эгер a == b, анда hash(a) жана hash(b) бирдей болушу керек. Артка кайтуу керек эмес (коллизиялар болушу мүмкүн).
  • Хеш-функциянын сапаты: Жакшы хеш-функция ар түрдүү ачкычтар үчүн хеш маанилерди бирдей бөлүштүрөт, коллизияларды минималдаштырат жана иштөө ылдамдыгын жакшыртат (O(1) орто эсеп менен).
  • Константтык: Теңдештирүү операторлору жана хеш-функция const болушу керек, анткени алар ачкыч объектисин өзгөртпөшү керек эмес.