Tabel hash versus pohon biner

30

Saat menerapkan kamus ('Saya ingin mencari data pelanggan dengan ID pelanggan mereka'), struktur data yang digunakan adalah tabel hash dan pohon pencarian biner. Saya tahu misalnya bahwa perpustakaan C ++ STL mengimplementasikan kamus (mereka menyebutnya peta) menggunakan pohon pencarian biner (seimbang), dan kerangka .NET menggunakan tabel hash di bawah tenda.

Apa kelebihan dan kekurangan dari struktur data ini? Apakah ada opsi lain yang masuk akal dalam situasi tertentu?

Perhatikan bahwa saya tidak terlalu tertarik pada kasus-kasus di mana kunci memiliki struktur dasar yang kuat, katakanlah, mereka semua bilangan bulat antara 1 dan n atau sesuatu.

Alex ten Brink
sumber
1
Saya akan menjengkelkan Anda, tetapi Anda tidak bisa hanya mengatakan "bilangan bulat antara 1 dan n" karena dalam hal itu array akan lebih cepat dari semua struktur data lainnya :-). "String" tampaknya adil dan mencakup sebagian besar situasi.
jmad
@jmad dia bilang dia tidak tertarik dengan kasus itu.
Joe
@ Jo, saya pikir sudah jelas saya memperhitungkan ini. Pokoknya itu bukan alasan untuk memberikan contoh kunci yang paling buruk.
jmad
1
Sebenarnya .NET memiliki kedua kamus diimplementasikan menggunakan pohon dan kamus diimplementasikan menggunakan tabel hash (dan begitu juga C ++ sejak standar 2011).
sepp2k
Kemungkinan sama pada SO: stackoverflow.com/questions/371136/…
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

Jawaban:

26

n

Jawaban singkatnya adalah bahwa tabel hash lebih cepat dalam banyak kasus , tetapi bisa sangat buruk pada yang terburuk. Pohon pencarian memiliki banyak keuntungan, termasuk perilaku terburuk yang jinak , tetapi agak lambat dalam kasus-kasus tertentu.

O(lg(n))log2(n)

2nO(1)

O(1)

  • O(n)
  • O(1)

Saat Anda melempar lokalitas data ke dalam campuran, tabel hash berkinerja buruk. Mereka bekerja dengan tepat karena mereka menyimpan elemen terkait secara berjauhan, yang berarti bahwa jika aplikasi mencari elemen yang berbagi awalan secara berurutan, itu tidak akan mendapat manfaat dari efek cache. Ini tidak relevan jika aplikasi pada dasarnya membuat pencarian acak.

Faktor lain yang mendukung pohon pencarian adalah bahwa mereka merupakan struktur data yang tidak dapat diubah : jika Anda perlu mengambil salinan pohon dan mengubah beberapa elemen di dalamnya, Anda dapat berbagi sebagian besar struktur data. Jika Anda mengambil salinan tabel hash, Anda perlu menyalin seluruh array pointer. Juga, jika Anda bekerja dalam bahasa yang murni fungsional, tabel hash seringkali bukan pilihan.

k1k2h(k1)=h(k2)

Secara khusus, jika Anda akan membutuhkan urutan pada tombol, misalnya jika Anda ingin dapat membuat daftar kunci dalam urutan abjad, maka tabel hash tidak membantu (Anda harus mengurutkannya), sedangkan Anda dapat langsung menelusuri pohon pencarian secara berurutan.

Anda dapat menggabungkan pohon pencarian biner dan tabel hash dalam bentuk pohon hash . Pohon hash menyimpan kunci di pohon pencarian sesuai hash mereka. Ini berguna, misalnya, dalam bahasa pemrograman murni fungsional di mana Anda ingin bekerja pada data yang tidak memiliki hubungan urutan yang mudah untuk dihitung.

Ketika kunci adalah string (atau bilangan bulat), trie bisa menjadi pilihan lain. Trie adalah pohon, tetapi diindeks berbeda dari pohon pencarian: Anda menulis kunci dalam biner, dan ke kiri untuk 0 dan kanan untuk 1. Biaya akses dengan demikian sebanding dengan panjang kunci. Mencoba dapat dikompresi untuk menghapus node perantara; ini dikenal sebagai patricia trie atau radix tree . Pohon radix dapat mengungguli pohon seimbang, terutama ketika banyak kunci berbagi awalan yang sama.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
2
Tidakkah BST juga memiliki lokalitas data yang buruk?
svick
@ svick Mereka mungkin atau mungkin tidak, tergantung pada bagaimana node dialokasikan. Meningkatkan arity pohon dapat membantu tanpa mengorbankan waktu berjalan (biayanya lebih besar dan kode lebih kompleks).
Gilles 'SO- stop being evil'
2
Pada BST mudah untuk mendapatkan elemen "dalam urutan", untuk tabel hash itu keluar dari pertanyaan.
vonbrand
Selain untuk alasan keamanan, mengapa masalah jika tabel hash memiliki waktu terburuk terburuk jika rata-rata mereka lebih baik daripada tabel biner? Saya membayangkan bahwa kenyamanan utilitas / pengguna memiliki hubungan linear yang kira-kira dengan berapa lama waktu yang diperlukan untuk menyelesaikan pohon, sehingga nilai (rata-rata) yang diharapkan harus menjadi yang terpenting.
Kelmikra
@ Kyth'Py1k Apa yang Anda maksud dengan "pohon untuk menyelesaikan"? Inti dari tabel hash adalah untuk mengakses satu nilai pada suatu waktu, bukan seluruh pohon, jika tidak daftar atau array akan bekerja lebih baik. Bahkan dalam situasi di mana nilai rata-rata adalah yang penting (yang tidak selalu terjadi, misalnya ketika Anda memiliki kendala waktu nyata), itu adalah rata-rata atas permintaan yang dibuat dalam situasi tertentu, yang seringkali sama sekali tidak seragam di atas meja - misalnya bias pada awalan tertentu.
Gilles 'SANGAT berhenti menjadi jahat'