0Pricing
C++ Academy · Ders

Özel Karma İşlevleri

Kendi türlerinizi karma değerine dönüştürün

Özel Karma İşlevleri, CoddyKit'te ücretsiz bir C++ Academy dersidir. Bu, 4 dersinin 3. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, C++ Academy öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. C++ Academy kursu toplamda 4 dersten oluşur.

Neden Özel Hash'ler?

Sırasız konteynerlerin anahtarlarına hash uygulamak için bir yönteme ihtiyacı vardır. Yerleşik türlerin ve std::string'in hash'leri zaten vardır; ancak kendi türlerinizde hash yoktur. Bir tane sağlamanız gerekir.

#include <iostream>
#include <unordered_set>
#include <string>

int main() {
    std::unordered_set<std::string> s{"hi"};
    std::cout << s.count("hi") << '\n';
    return 0;
}

std::hash Şablonu

std::hash, bir değeri size_t'ye eşleyen bir fonksiyon nesnesidir. Onu bir işlev gibi çağırırsınız.

#include <iostream>
#include <functional>
#include <string>

int main() {
    std::hash<std::string> h;
    std::cout << "hash exists and returns a size_t\n";
    std::size_t v = h("hello");
    std::cout << (v != 0 ? "non-zero hash" : "zero") << '\n';
    return 0;
}

Hash Uygulanacak Bir Yapı

İki int içeren bir Point değerimiz olduğunu varsayalım. Bunu bir unordered_set'te saklamak için hem eşitliğe hem de bir hash'e ihtiyacımız vardır.

#include <iostream>

struct Point {
    int x, y;
    bool operator==(const Point& o) const { return x == o.x && y == o.y; }
};

int main() {
    Point a{1, 2}, b{1, 2};
    std::cout << std::boolalpha << (a == b) << '\n';
    return 0;
}

Hash Fonksiyon Nesnesi Yazma

Bir hash fonksiyon nesnesi, size_t döndüren operator() içeren bir yapıdır. Alanların hash'lerini çoğunlukla XOR ve bir kaydırma kullanarak birleştirin.

#include <iostream>
#include <functional>

struct Point { int x, y; };

struct PointHash {
    std::size_t operator()(const Point& p) const {
        return std::hash<int>()(p.x) ^ (std::hash<int>()(p.y) << 1);
    }
};

int main() {
    PointHash h;
    std::cout << "hashed: " << (h({3, 4}) != 0 ? "ok" : "zero") << '\n';
    return 0;
}

Hash Fonksiyon Nesnesini Kullanma

Hash fonksiyon nesnesini sırasız konteynerin ikinci şablon bağımsız değişkeni olarak aktarın.

#include <iostream>
#include <unordered_set>
#include <functional>

struct Point {
    int x, y;
    bool operator==(const Point& o) const { return x == o.x && y == o.y; }
};

struct PointHash {
    std::size_t operator()(const Point& p) const {
        return std::hash<int>()(p.x) ^ (std::hash<int>()(p.y) << 1);
    }
};

int main() {
    std::unordered_set<Point, PointHash> pts;
    pts.insert({1, 2});
    pts.insert({1, 2});
    std::cout << pts.size() << '\n';
    return 0;
}

Eşitlik de Gereklidir

Hash'leri çakıştığında iki anahtar aynı bucket'a yerleşir. Ardından konteyner, bunları birbirinden ayırmak için operator== kullanır; bu nedenle eşitlik zorunludur.

#include <iostream>
#include <unordered_set>

struct Point {
    int x, y;
    bool operator==(const Point& o) const { return x == o.x && y == o.y; }
};

struct PointHash {
    std::size_t operator()(const Point& p) const {
        return std::hash<int>()(p.x * 31 + p.y);
    }
};

int main() {
    std::unordered_set<Point, PointHash> s{{1, 1}, {2, 2}};
    std::cout << s.count({1, 1}) << '\n';
    return 0;
}

Bir map Anahtarına Hash Uygulama

Aynı özel hash, bir yapının unordered_map'te anahtar olmasını sağlar.

#include <iostream>
#include <unordered_map>
#include <functional>

struct Point {
    int x, y;
    bool operator==(const Point& o) const { return x == o.x && y == o.y; }
};

struct PointHash {
    std::size_t operator()(const Point& p) const {
        return std::hash<int>()(p.x) ^ (std::hash<int>()(p.y) << 1);
    }
};

int main() {
    std::unordered_map<Point, std::string, PointHash> m;
    m[{0, 0}] = "origin";
    std::cout << m[{0, 0}] << '\n';
    return 0;
}

Birden Çok Alanı Birleştirme

Yaygın bir yardımcı, boost::hash_combine'a benzer çarpan ve toplama düzenini kullanarak hash'leri her seferinde bir alan olacak şekilde birleştirir.

#include <iostream>
#include <functional>

std::size_t combine(std::size_t seed, std::size_t v) {
    return seed ^ (v + 0x9e3779b9 + (seed << 6) + (seed >> 2));
}

int main() {
    std::size_t h = 0;
    h = combine(h, std::hash<int>()(10));
    h = combine(h, std::hash<int>()(20));
    std::cout << (h != 0 ? "combined ok" : "zero") << '\n';
    return 0;
}

İyi Hash Dağılımı

Sabit bir değer döndüren kötü bir hash, her şeyi tek bir bucket'a yerleştirerek performansı O(n)'e düşürür. Tüm alanların bitlerini iyi şekilde karıştırın.

#include <iostream>
#include <functional>

struct Bad { std::size_t operator()(int) const { return 0; } };
struct Good { std::size_t operator()(int x) const { return std::hash<int>()(x); } };

int main() {
    std::cout << Bad()(5) << ' ' << (Good()(5) != 0 ? "varies" : "0") << '\n';
    return 0;
}

std::hash Özelleştirmesi

Alternatif olarak, bir fonksiyon nesnesini açıkça aktarmadan çalışması için kendi türünüz için std::hash'i özelleştirin.

#include <iostream>
#include <unordered_set>

struct Point {
    int x, y;
    bool operator==(const Point& o) const { return x == o.x && y == o.y; }
};

namespace std {
    template <> struct hash<Point> {
        std::size_t operator()(const Point& p) const {
            return hash<int>()(p.x) ^ (hash<int>()(p.y) << 1);
        }
    };
}

int main() {
    std::unordered_set<Point> s{{1, 2}};
    std::cout << s.count({1, 2}) << '\n';
    return 0;
}

Hash Olarak Lambda

C++20'de, türünü aktararak durumsuz bir lambda'yı hash olarak bile kullanabilirsiniz.

#include <iostream>
#include <unordered_set>

int main() {
    auto h = [](int x) { return std::hash<int>()(x * 2654435761u); };
    std::unordered_set<int, decltype(h)> s(8, h);
    s.insert(42);
    std::cout << s.count(42) << '\n';
    return 0;
}

Hızlı Kontrol

Özel hash uygulama konusundaki anlayışınızı sınayın.

Özet

Özel türlere hash uygulamayı öğrendiniz:

  • size_t döndüren bir hash fonksiyon nesnesi sağlayın (veya std::hash'i özelleştirin)
  • çakışan anahtarların birbirinden ayırt edilebilmesi için ayrıca operator== sağlayın
  • iyi bir dağılım elde etmek için alanların hash'lerini iyi şekilde birleştirin

Sırada, bucket'ları ve yük faktörünün performansını inceleyeceksiniz.

Sıkça Sorulan Sorular

“Özel Karma İşlevleri” dersi ücretsiz mi?

Evet — “Özel Karma İşlevleri” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve C++ Academy kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. C++ Academy kursu toplamda 4 dersten oluşur.

“Özel Karma İşlevleri” dersinde ne öğreneceğim?

Kendi türlerinizi karma değerine dönüştürün C++ Academy ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.

C++ Academy öğrenmeye başlamak için deneyim gerekli mi?

Önceden deneyim gerekmez. CoddyKit'te C++ Academy, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 3. dersidir.

“Özel Karma İşlevleri” dersi ne kadar sürer?

Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.

Bu C++ Academy dersinde kod yazıp çalıştırabilir miyim?

Evet. Her C++ Academy dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.

Bu kursun tüm dersleri

  1. std::unordered_map
  2. unordered_set
  3. Özel Karma İşlevleri
  4. Performans Değerlendirmeleri
← C++ Academy Sayfasına Dön