Bagaimana tabel hash O (1) memperhitungkan kecepatan hashing akun?

8

Tabel hash dikatakan diamortisasi menggunakan rantai sederhana dan dua kali lipat pada kapasitas tertentu.Θ(1)

Namun, ini mengasumsikan panjang elemen konstan. Menghitung hash suatu elemen membutuhkan melalui elemen, mengambil waktu di mana adalah panjangnya.Θ(l)l

Tetapi untuk membedakan antara elemen, kita membutuhkan elemen yang memiliki panjang setidaknya bit; jika tidak dengan prinsip pigeonhole mereka tidak akan berbeda. Fungsi hash melalui bit elemen akan memakan waktu .nlgnlgnΘ(lgn)

Jadi bisakah kita mengatakan bahwa kecepatan tabel hash, dengan mempertimbangkan fungsi hash yang masuk akal yang menggunakan semua bagian dari input, sebenarnya ? Lalu, mengapa tabel hash dalam praktiknya efisien untuk menyimpan elemen panjang variabel, seperti string dan integer besar?Θ(lgn)

ithisa
sumber
4
Jawabannya adalah tidak . Jenis analisis hashing tidak memperhitungkan dimensi (atau jumlah bit) elemen, tetapi hanya banyak.
Nikos M.
Tetapi jika pencarian peta hash yang akan menjadi tidak mempertimbangkan membaca dan menulis bit seperti yang dijelaskan, adalah , maka di bawah kriteria yang sama, pencarian biner atau proses lain yang kami biasanya mempertimbangkan akan benar-benar menjadi bukan? Θ(1)Θ(lg n)Θlg nΘ(lg2 n)
5
@tAllan cf seragam vs model biaya logaritmik .
Raphael
@tAllan Pencarian biner biasa adalah tetapi jika Anda menyimpan item diurutkan berdasarkan urutan bit kunci mereka dan melakukan pencarian biner membandingkan "satu bit pada satu waktu" (rincian rumit dihilangkan), Anda mungkin dapat mencapai . Θ(log2n)Θ(logn)
Pasang kembali Monica

Jawaban:

3

Kisah bahwa tabel hash diamortisasi adalah kebohongan penyederhanaan berlebihan. Θ(1)

Ini hanya berlaku jika:
- Jumlah data untuk hash per item sepele dibandingkan dengan jumlah K eys dan kecepatan hashing K ey cepat - . - Jumlah C ollisions kecil - . - Kami tidak memperhitungkan waktu akun yang dibutuhkan untuk R esize tabel hash - .k
c
r

String besar untuk hash
Jika asumsi pertama salah, waktu berjalan akan naik ke . Ini benar untuk string besar, tetapi untuk string besar perbandingan sederhana juga akan memiliki waktu berjalan . Jadi hash tidak lebih lambat secara asimptot, meskipun hashing akan selalu lebih lambat daripada perbandingan sederhana, karena perbandingan memiliki awal memilih keluar ergo , dan hashing selalu harus hash string penuh , . Θ(k)
Θ(k)O(1)Ω(k)O(k)Ω(k)

Perhatikan bahwa bilangan bulat tumbuh sangat lambat. 8 byte dapat menyimpan nilai hingga ; 8 byte adalah jumlah yang sepele untuk hash. Jika Anda ingin menyimpan bigints maka anggap saja itu sebagai string. 1018

Algoritma hash lambat
Jika hashing pengeluaran jumlah adalah non-sepele dibandingkan dengan penyimpanan data maka jelas asumsi menjadi tidak bisa dipertahankan. Kecuali jika hash kriptografi digunakan, ini seharusnya tidak menjadi masalah.Θ(1)

Yang penting . Selama itu berlaku adalah pernyataan yang adil.n >> kΘ(1)

Banyak tabrakan
Jika fungsi hashing buruk, atau tabel hash kecil, atau ukuran tabel hash canggung tabrakan akan sering dan waktu berjalan akan pergi ke . Fungsi hashing harus dipilih sehingga tabrakan jarang terjadi sementara masih secepat mungkin, ketika ragu-ragu memilih tabrakan yang lebih sedikit dengan mengorbankan hashing yang lebih lambat. Aturan praktisnya adalah bahwa tabel hashing harus selalu kurang dari 75% penuh. Dan ukuran tabel hashing seharusnya tidak memiliki korelasi dengan fungsi hashing. Seringkali ukuran tabel hashing (relatif) prima. O(log(n))



Mengubah ukuran tabel hash
Karena tabel hash yang hampir penuh akan memberikan terlalu banyak tabrakan dan tabel hash (kosong) yang besar adalah pemborosan ruang, banyak implementasi yang memungkinkan tabel hash untuk tumbuh (dan menyusut!) Sesuai kebutuhan.
Pertumbuhan tabel dapat melibatkan salinan lengkap semua item (dan mungkin perombakan), karena penyimpanan harus kontinu untuk alasan kinerja.
Hanya dalam kasus-kasus patologis perubahan ukuran tabel hash menjadi masalah sehingga ukuran (mahal tapi jarang) diamortisasi di banyak panggilan.

Running time
Jadi waktu running sebenarnya dari tabel hash adalah . Setiap , , rata-rata diasumsikan sebagai konstanta (kecil) dalam waktu berjalan diamortisasi dan dengan demikian kita mengatakan bahwa adalah pernyataan yang adil. Θ(kcr)
kcrΘ(1)

Untuk kembali ke pertanyaan Anda.
Maafkan saya karena parafrase, saya sudah mencoba untuk mengekstrak berbagai makna, jangan ragu untuk berkomentar jika saya melewatkan beberapa

Anda tampaknya khawatir tentang panjang output dari fungsi hash. Sebut ini ( umumnya dianggap jumlah item yang akan di-hash). akan menjadi karena m perlu mengidentifikasi entri dalam tabel hash secara unik. Ini berarti bahwa m tumbuh sangat lambat. Pada 64 bit jumlah entri tabel hash akan mengambil porsi yang cukup besar dari RAM yang tersedia di seluruh dunia. Pada 128 bit itu akan jauh melebihi penyimpanan disk yang tersedia di planet bumi. Memproduksi hash 128 bit tidak jauh lebih sulit daripada hash 32 bit, jadi tidak , waktu untuk membuat hash bukanlah (atau jika Anda mau). mnmlog(n)

O(m)O(log(n))

Fungsi hash melalui bit elemen akan memakan waktu waktu. log(n)Θ(log(n))

Tetapi fungsi hash tidak melalui bit elemen. Per satu item (!!) hanya berlaku untuk data . Juga panjang input (k) tidak ada hubungannya dengan jumlah elemen. Ini penting, karena beberapa algoritma non hashing harus memeriksa banyak elemen dalam koleksi untuk menemukan elemen (non) yang cocok. Tabel hash hanya melakukan perbandingan 1 atau 2 per item yang sedang dipertimbangkan rata-rata sebelum mencapai kesimpulan. log(n)
O(k)

Mengapa tabel hash efisien untuk menyimpan elemen panjang variabel?

Karena terlepas dari panjang input ( ) panjang output ( ) selalu sama, tabrakan jarang terjadi dan waktu pencarian konstan. Namun ketika panjang kunci tumbuh besar dibandingkan dengan jumlah item dalam tabel hash ( ) cerita berubah ...km
kn

Mengapa tabel hash efisien untuk menyimpan string besar?

Tabel hash tidak terlalu efisien untuk string yang sangat besar.

Jika (yaitu ukuran input agak besar dibandingkan dengan jumlah item dalam tabel hash) maka kita tidak bisa lagi mengatakan bahwa hash memiliki waktu berjalan yang konstan, tetapi harus beralih ke waktu berjalan dari terutama karena tidak ada awal. Anda harus hash kunci lengkap. Jika Anda hanya menyimpan sejumlah item terbatas, maka Anda mungkin jauh lebih baik menggunakan penyimpanan yang diurutkan, karena ketika membandingkan Anda dapat memilih keluar segera setelah perbedaan terlihat. not n>>kΘ(k)k1 k2

Namun, jika Anda mengetahui data Anda, Anda dapat memilih untuk tidak meng-hash kunci penuh, tetapi hanya bagian (dikenal atau diasumsikan) yang volatil darinya, memulihkan properti sembari tetap menjaga tabrakan tetap terkendali. Θ(1)

Konstanta Tersembunyi
Karena semua orang harus tahu berarti bahwa waktu per elemen yang diproses adalah konstan. Konstanta ini sedikit lebih besar untuk hashing daripada untuk perbandingan sederhana. Untuk tabel kecil, pencarian biner akan lebih cepat daripada pencarian hash, karena misalnya 10 perbandingan biner mungkin lebih cepat daripada hash tunggal. Untuk dataset kecil, alternatif untuk tabel hash harus dipertimbangkan. Ada pada dataset besar yang tabel hash benar-benar bersinar.Θ(1)


Johan
sumber
Saya tidak mengerti definisi Anda tentang . Itu tidak benar bahwa mengubah ukuran meningkatkan runtime diamortisasi. Selama Anda melakukan pengubahan ukuran secara tepat, biaya penyalinan dapat diamortisasi dan tidak meningkatkan runtime diamortisasi. Saya tidak berpikir kecepatan hash pernah menjadi masalah (bahkan hash kriptografi sangat cepat; dan dalam hal apapun, mereka berjalan dalam waktu yang konstan, jika panjang input dibatasi oleh konstanta). The klaim runtime selalu bergantung pada menggunakan fungsi yang baik hash (sehingga tabrakan akan sedikit). k,c,rO(1)
DW
1
Jadi dari masalah yang Anda sebutkan, saya pikir hanya panjang input yang benar-benar masalah serius. Juga, ini tidak benar-benar menjawab pertanyaan yang ditanyakan. Pertanyaan berbicara tentang panjang output dan panjang output sebaiknya dianggap sebagai bit daripada bit. Itu benar, tetapi apa yang dilihatnya adalah model komputasi yang digunakan untuk menghitung waktu berjalan . Jawaban ini tampaknya tidak masuk ke semua itu, jadi saya tidak yakin ini adalah masalah yang diangkat dalam pertanyaan. Ω(lgn)O(1)O(1)
DW
Saya ingin lengkap dengan semua elemen waktu berjalan. Kami setuju bahwa hanya panjang kunci yang benar-benar menjadi perhatian saat hashing. Saya memperbaiki masalah log (n) yang diangkat OP. Saya salah membaca itu, karena itu bukan masalah ketika hashing IMO.
Johan
Saya harap jawabannya lebih selaras dengan pertanyaan OP sekarang.
Johan
3

Mari kita mulai dengan pertanyaan yang lebih sederhana. Pertimbangkan apa yang mungkin merupakan struktur data paling sederhana yang ada, sebuah array . Untuk konkret, mari kita bayangkan sebuah array bilangan bulat. Berapa lama waktu yang dibutuhkan oleh operasi ? Jawabannya tergantung pada model perhitungan. Dua model relevan di sini: model RAM (yang lebih umum) dan model bit (yang lebih mudah dijelaskan).A[i]=A[j]

Dalam model yang sedikit , operasi dasar yang melibatkan bit biaya . Jadi jika bilangan bulat lebar bit, operasi akan menelan biaya sekitar .NNwA[i]=A[j]2w

Dalam model RAM , unit dasar data tidak sedikit tetapi kata (kadang-kadang dikenal sebagai kata mesin ). Kata adalah bilangan bulat dengan lebar , di mana adalah ukuran input (dalam bit). Operasi dasar yang melibatkan kata biaya . Dalam kebanyakan kasus, jika Anda memiliki array bilangan bulat maka bilangan bulat yang Anda butuhkan memiliki lebar , sehingga operasi biaya .lognnNNO(logn)A[i]=A[j]O(1)

Seperti yang saya katakan di atas, kami biasanya menganalisis algoritma menggunakan model RAM. Satu-satunya pengecualian yang umum adalah bilangan bulat aritmatika, khususnya perkalian bilangan bulat, yang sering dianalisis sehubungan dengan jumlah operasi bit.

Mengapa kita menggunakan model RAM? Karena memiliki kekuatan yang lebih prediktif (vis a vis realitas). Asumsi bahwa ukuran input paling eksponensial dalam ukuran kata mesin biasanya dibenarkan, terutama untuk prosesor 64-bit modern, dan operasi pada kata-kata mesin memakan waktu konstan dalam CPU yang sebenarnya.


Tabel hash adalah struktur data yang lebih rumit, dan mereka benar-benar melibatkan tiga jenis: tipe kunci, tipe hash, dan tipe nilai. Dari sudut pandang tipe nilai , tabel hash hanyalah array yang dimuliakan, jadi mari kita abaikan aspek itu. The tipe hash selalu dapat diasumsikan terdiri dari sejumlah kecil kata mesin. The jenis kunci memenuhi properti khusus: itu adalah hashable , yang berarti bahwa ia memiliki operasi hash yang (minimal) adalah beberapa fungsi deterministik (fungsi selalu mengembalikan nilai yang sama).

Kami sekarang dapat menjawab pertanyaan Anda: berapa lama waktu yang dibutuhkan untuk memotong kunci? Jawabannya tergantung pada model perhitungan. Kali ini kami memiliki tiga model umum: dua model sebelumnya, dan model oracle.

Dalam model oracle , kita mengasumsikan bahwa fungsi hash diberikan kepada kita oleh "oracle" yang dapat menghitung hash dari kunci arbitrer dalam waktu yang konstan.

Dalam model RAM dan model bit , fungsi hash adalah fungsi yang sebenarnya, dan kompleksitas waktu dari tabel hash tergantung pada kompleksitas waktu dari fungsi hash. Fungsi hash yang digunakan untuk tabel hash (bukan untuk keperluan kriptografi) biasanya sangat cepat, dan membutuhkan waktu linier dalam input. Itu berarti bahwa jika tipe kunci memiliki panjang bit (dalam model bit) atau kata (dalam model RAM), fungsi hash membutuhkan waktu . Ketika adalah konstanta, fungsi hash membutuhkan waktu yang konstan.NNO(N)N

Ketika kami menganalisis waktu berjalan dari algoritma tabel hash, kami biasanya secara implisit menggunakan model oracle. Ini sering dinyatakan dalam bahasa yang berbeda: kami hanya mengatakan bahwa kami menghitung jumlah pemanggilan fungsi hash. Ini masuk akal, karena biasanya aplikasi fungsi hash adalah istilah dominan dalam waktu berjalan algoritma tabel hash, dan untuk menganalisis kompleksitas waktu aktual, yang harus Anda lakukan adalah mengalikan jumlah doa hash dengan waktu berjalan dari fungsi hash.

Ketika menganalisis waktu berjalan suatu algoritma menggunakan tabel hash sebagai struktur data, kita sering tertarik pada waktu berjalan yang sebenarnya, biasanya dalam model RAM. Salah satu opsi di sini adalah untuk melakukan apa yang disarankan dalam paragraf sebelumnya, yaitu untuk mengalikan waktu berjalan operasi tabel hash (diberikan dalam hal jumlah pemanggilan fungsi hash) dengan waktu berjalan fungsi hash.

Namun, ini tidak cukup baik jika tombol memiliki panjang yang bervariasi. Sebagai contoh, bayangkan kita memiliki kunci ukuran , dan kita menghitung hash masing-masing sekali. Kompleksitas waktu aktual adalah , tetapi perhitungan di atas hanya menghasilkan . Jika hal ini terjadi pada beberapa aplikasi, kita dapat memperhitungkannya secara ad hoc, menggunakan analisis yang disempurnakan dari kompleksitas tabel hash yang mendasarinya.1,2,4,,2mO(2m)O(m2m)

Yuval Filmus
sumber