๐Ÿ—‚๏ธ Hash Table

Struktur Data dan Algoritma

Pertemuan 14

Universitas Pertahanan RI

๐ŸŽฏ Tujuan Pembelajaran

Setelah pertemuan ini, mahasiswa mampu:

  1. Menjelaskan konsep hashing dan keunggulannya
  2. Merancang fungsi hash yang baik
  3. Mengidentifikasi penyebab collision
  4. Mengimplementasikan separate chaining
  5. Mengimplementasikan open addressing
  6. Menganalisis kompleksitas operasi hash table

๐Ÿ“‹ Agenda

Bagian 1

  1. Motivasi & Konsep Hashing
  2. Fungsi Hash
  3. Collision

Bagian 2

  1. Separate Chaining
  2. Open Addressing
  3. Load Factor & Rehashing
  4. Aplikasi

๐Ÿ“– 1. Motivasi Hash Table

Permasalahan: Menyimpan & mengakses data personel berdasarkan NIK

Struktur Data Search Masalah
Array unsorted O(n) Terlalu lambat
Array sorted O(log n) Insert/Delete lambat
BST balanced O(log n) Bisa tidak seimbang
Hash Table O(1) โœ“ Ideal!

Direct Addressing

Ide: Gunakan key sebagai index array langsung


int table[1000];

// Insert
table[key] = value;   // O(1)

// Search
return table[key];    // O(1)

// Delete
table[key] = -1;      // O(1)
                    

โš ๏ธ Masalah: NIK 16 digit โ†’ perlu array 10^16 slot!

Konsep Hashing

Hashing adalah teknik memetakan key dari domain besar ke domain lebih kecil menggunakan fungsi hash h(k).

Konsep Hashing

Gambar 14.1: Konsep dasar hashing

Komponen Hash Table

๐Ÿ“ฆ Array

Ukuran m (bucket/slot)

โš™๏ธ Fungsi Hash

h: U โ†’ {0,1,...,m-1}

๐Ÿ”ง Collision Handling

Jika h(kโ‚) = h(kโ‚‚)

๐Ÿ“– 2. Fungsi Hash

Karakteristik Fungsi Hash yang Baik

  1. Deterministic: Key sama โ†’ hash sama
  2. Uniform Distribution: Menyebar merata
  3. Efficient: Cepat dihitung O(1)
  4. Minimize Collision: Key berbeda โ†’ hash berbeda

Division Method

h(k) = k mod m


int hashDivision(int key, int m) {
    return key % m;
}

// h(12345) dengan m = 97
// = 12345 % 97 = 70
                    

๐Ÿ’ก Tips: Pilih m = bilangan prima (97, 193, 389, ...)

Multiplication Method

h(k) = floor(m ร— (k ร— A mod 1))

A โ‰ˆ 0.618 (golden ratio)


int hashMultiplication(int key, int m) {
    const double A = 0.6180339887;
    double temp = key * A;
    temp = temp - (int)temp;  // Bagian fraksional
    return (int)(m * temp);
}
                    

Keuntungan: Nilai m tidak kritis, bisa power of 2

Hash untuk String

Polynomial Rolling Hash:


unsigned long hashString(const string& key, int m) {
    unsigned long hash = 0;
    unsigned long base = 31;  // Bilangan prima
    
    for (char c : key) {
        hash = (hash * base + c) % m;
    }
    
    return hash;
}

// hash("abc", 100) = 54
                    

๐Ÿง  Quiz: Fungsi Hash

Mengapa m = 100 bukan pilihan baik untuk division method?

Karena m = 100 = 10ยฒ hanya menggunakan 2 digit terakhir key:

  • h(123456) = 56
  • h(789456) = 56 โ†’ Collision!
  • Tidak memanfaatkan informasi digit lain

Solusi: Gunakan bilangan prima (97, 101)

๐Ÿ“– 3. Collision

Collision terjadi ketika dua key berbeda kโ‚ โ‰  kโ‚‚ menghasilkan hash value sama: h(kโ‚) = h(kโ‚‚)

Collision

Gambar 14.2: Ilustrasi collision

Mengapa Collision Pasti Terjadi?

Pigeonhole Principle:

Jika n item dimasukkan ke m slot (n > m), minimal satu slot berisi lebih dari satu item.

Birthday Paradox:

Dalam grup 23 orang, P(2 orang birthday sama) > 50%!

Dua Pendekatan Collision Handling

Pendekatan Teknik Ide Dasar
Separate Chaining Linked List Chain di setiap slot
Open Addressing Probing Cari slot kosong lain

Contoh Collision

h(k) = k mod 7

Key Hash Status
3 3 mod 7 = 3 OK
10 10 mod 7 = 3 Collision!
17 17 mod 7 = 3 Collision!
24 24 mod 7 = 3 Collision!

Pola: Semua key bentuk 7k + 3 collision di slot 3

๐Ÿ“– 4. Separate Chaining

Separate Chaining menyimpan semua key dengan hash sama dalam linked list di slot tersebut.

Separate Chaining

Gambar 14.3: Hash table dengan separate chaining

๐Ÿ’ป Implementasi Insert


void insert(int key, const string& value) {
    int index = hash(key);
    
    // Cek apakah key sudah ada
    for (auto& pair : table[index]) {
        if (pair.first == key) {
            pair.second = value;  // Update
            return;
        }
    }
    
    // Key belum ada, tambahkan
    table[index].push_back({key, value});
}
                    

๐Ÿ’ป Implementasi Search & Delete


// Search
string* search(int key) {
    int index = hash(key);
    for (auto& pair : table[index]) {
        if (pair.first == key) {
            return &pair.second;
        }
    }
    return nullptr;  // Not found
}

// Delete
bool remove(int key) {
    int index = hash(key);
    for (auto it = table[index].begin(); it != table[index].end(); ++it) {
        if (it->first == key) {
            table[index].erase(it);
            return true;
        }
    }
    return false;
}
                    

Kompleksitas Separate Chaining

Operasi Average Worst Case
Insert O(1) O(n)
Search O(1 + ฮฑ) O(n)
Delete O(1 + ฮฑ) O(n)

ฮฑ = n/m adalah load factor

๐Ÿ“– 5. Open Addressing

Open Addressing menyimpan semua elemen dalam array. Jika slot terisi, cari slot kosong dengan probing.

Aspek Separate Chaining Open Addressing
Struktur tambahan Linked list Tidak ada
Load factor max > 1 โ‰ค 1
Cache performance Buruk Baik

Linear Probing

h(k, i) = (h'(k) + i) mod m

i = 0, 1, 2, 3, ... (nomor percobaan)

Linear Probing

Gambar 14.4: Linear probing

๐Ÿ’ป Insert dengan Linear Probing


bool insert(int key, const string& value) {
    int index = hash(key);
    int i = 0;
    
    do {
        int probeIndex = (index + i) % size;
        
        // Slot kosong - bisa insert
        if (!occupied[probeIndex]) {
            keys[probeIndex] = key;
            values[probeIndex] = value;
            occupied[probeIndex] = true;
            return true;
        }
        
        // Linear probe: cek slot berikutnya
        i++;
        
    } while (i < size);
    
    return false;  // Table penuh
}
                    

Masalah: Primary Clustering

Primary Clustering: Terbentuknya cluster (kelompok slot terisi berurutan) yang semakin besar.

Jika ada cluster panjang k:

  • Key baru yang hash ke salah satu slot โ†’ cluster jadi k+1
  • Probe sequence makin panjang

Quadratic Probing

h(k, i) = (h'(k) + cโ‚ยทi + cโ‚‚ยทiยฒ) mod m

Bentuk sederhana: h(k, i) = (h'(k) + iยฒ) mod m

Probe sequence untuk h'(k) = 5, m = 11:

i 0 1 2 3 4
Slot 5 6 9 3 10

Double Hashing

h(k, i) = (hโ‚(k) + i ยท hโ‚‚(k)) mod m


int h1(int k) { return k % m; }
int h2(int k) { return 1 + (k % (m-1)); }

int doubleHash(int k, int i, int m) {
    return (h1(k) + i * h2(k)) % m;
}
                    

โœ“ Menghindari clustering
โœ“ Distribusi probe lebih merata

๐Ÿง  Quiz: Linear Probing

Insert key 10, 22, 31, 4, 15 ke hash table m=11, h(k)=k mod 11.

Di mana posisi akhir key 15?

Key h(k) Probes Position
10101010
22000
31999
4444
1544โ†’55

Lazy Deletion

Masalah: Hard delete di open addressing merusak probe sequence!

Solusi: Tandai slot sebagai "DELETED" bukan "EMPTY"

  • Search: lanjut probing melewati DELETED
  • Insert: bisa reuse DELETED slot
  • Periodic rehashing untuk cleanup

๐Ÿ“– 6. Load Factor & Rehashing

Load Factor (ฮฑ) = n / m

Rasio jumlah elemen terhadap ukuran tabel

ฮฑ Interpretasi Performa
0.2525% terisiSangat baik
0.5050% terisiBaik
0.7575% terisiThreshold standar
0.9090% terisiDegradasi

Rehashing

Rehashing adalah proses membuat hash table baru lebih besar dan memindahkan semua elemen.

Kapan rehashing?

  • Load factor > threshold (0.75)
  • Terlalu banyak slot DELETED

Contoh: ฮฑ = 0.8 โ†’ rehash 2ร— โ†’ ฮฑ baru = 0.4

Expected Probes (Open Addressing)

ฮฑ Unsuccessful Successful
0.50 2 probes 1.39 probes
0.75 4 probes 1.85 probes
0.90 10 probes 2.56 probes
0.95 20 probes 3.15 probes

Kesimpulan: Jaga ฮฑ โ‰ค 0.75 untuk performa baik!

๐Ÿ“Š Perbandingan Struktur Data

Struktur Data Search Insert Delete
Array (unsorted) O(n) O(1) O(n)
Array (sorted) O(log n) O(n) O(n)
BST (balanced) O(log n) O(log n) O(log n)
Hash Table O(1) avg O(1) avg O(1) avg

๐Ÿ“– 7. Aplikasi Hash Table

Umum

  • Dictionary/Map
  • Set (unique elements)
  • Counting/Frequency
  • Caching (LRU Cache)

๐ŸŽ–๏ธ Pertahanan

  • Database Personel (NIK/NRP)
  • Tracking Aset
  • Authentication
  • Activity Logging

๐Ÿ’ป Contoh: Counting


#include <unordered_map>

// Menghitung frekuensi karakter
string text = "hello world";
unordered_map<char, int> freq;

for (char c : text) {
    freq[c]++;  // O(1) per karakter
}

// freq['l'] = 3, freq['o'] = 2, ...
                    

๐Ÿ’ป Contoh: Find Intersection


vector<int> findIntersection(const vector<int>& arr1, 
                             const vector<int>& arr2) {
    // Masukkan arr1 ke hash set - O(n)
    unordered_set<int> set1(arr1.begin(), arr1.end());
    
    // Cek arr2 yang ada di set1 - O(m)
    vector<int> result;
    for (int num : arr2) {
        if (set1.count(num)) {
            result.push_back(num);
            set1.erase(num);  // Avoid duplicates
        }
    }
    
    return result;  // Total: O(n + m)
}
                    

Tanpa hash table: O(n ร— m)

๐Ÿ“ Ringkasan

Konsep Deskripsi
Hash Table Struktur data dengan O(1) average access
Fungsi Hash Division (k mod m), Multiplication, Polynomial
Collision h(kโ‚) = h(kโ‚‚), pasti terjadi (Pigeonhole)
Separate Chaining Linked list di setiap slot
Open Addressing Linear, Quadratic, Double Hashing
Load Factor ฮฑ = n/m, threshold 0.75
Rehashing Resize table saat ฮฑ tinggi

๐Ÿง  Quiz Akhir

Hash table dengan n = 600 elemen dan m = 800 slot.

  1. Berapa load factor?
  2. Apakah perlu rehashing (threshold 0.75)?

Jawaban:

  1. ฮฑ = n/m = 600/800 = 0.75
  2. ฮฑ = 0.75 tepat di threshold โ†’ perlu rehashing untuk insert berikutnya

โ“ Pertanyaan?

Silakan bertanya atau diskusi

Referensi: Cormen Ch.11 | Weiss Ch.5 | Hubbard Ch.8

Terima Kasih! ๐Ÿ™

Struktur Data dan Algoritma

Pertemuan 14

ยฉ 2026 - CC BY 4.0