Apa keuntungan dari pohon pencarian biner dibandingkan tabel hash?
Tabel hash dapat mencari elemen apa pun dalam waktu Theta (1) dan semudah menambahkan elemen .... tapi saya tidak yakin keuntungannya sebaliknya.
data-structures
hashtable
binary-search-tree
Berbakti
sumber
sumber
Jawaban:
Ingatlah bahwa Binary Search Trees (berbasis referensi) hemat memori. Mereka tidak menyimpan lebih banyak memori dari yang mereka butuhkan.
Misalnya, jika fungsi hash memiliki rentang
R(h) = 0...100
, Anda perlu mengalokasikan larik yang terdiri dari 100 elemen (pointers-to), meskipun Anda hanya mencirikan 20 elemen. Jika Anda menggunakan pohon pencarian biner untuk menyimpan informasi yang sama, Anda hanya akan mengalokasikan ruang sebanyak yang Anda butuhkan, serta beberapa metadata tentang tautan.sumber
Satu keuntungan yang belum ditunjukkan oleh orang lain adalah bahwa pohon pencarian biner memungkinkan Anda melakukan pencarian jangkauan secara efisien.
Untuk mengilustrasikan ide saya, saya ingin membuat kasus yang ekstrim. Katakanlah Anda ingin mendapatkan semua elemen yang kuncinya antara 0 hingga 5000. Dan sebenarnya hanya ada satu elemen tersebut dan 10.000 elemen lainnya yang kuncinya tidak berada dalam kisaran. BST dapat melakukan pencarian jarak dengan cukup efisien karena tidak mencari subpohon yang tidak mungkin mendapatkan jawabannya.
Sementara, bagaimana Anda bisa melakukan pencarian rentang dalam tabel hash? Anda juga perlu mengulang setiap ruang keranjang, yaitu O (n), atau Anda harus mencari apakah masing-masing dari 1,2,3,4 ... hingga 5.000 ada. (bagaimana dengan kunci antara 0 dan 5000 adalah himpunan tak terbatas? misalnya kunci dapat berupa desimal)
sumber
Satu "keuntungan" dari pohon biner adalah ia dapat dilintasi untuk mencantumkan semua elemen secara berurutan. Ini bukan tidak mungkin dengan tabel Hash tetapi bukan operasi normal satu desain ke dalam struktur hash.
sumber
Selain semua komentar bagus lainnya:
Tabel hash secara umum memiliki perilaku cache yang lebih baik yang membutuhkan lebih sedikit pembacaan memori dibandingkan dengan pohon biner. Untuk tabel hash, Anda biasanya hanya dikenakan satu kali baca sebelum Anda memiliki akses ke referensi yang menyimpan data Anda. Pohon biner, jika merupakan varian yang seimbang, membutuhkan sesuatu dalam urutan memori k * lg (n) yang dibaca untuk beberapa k konstan.
Di sisi lain, jika musuh mengetahui fungsi hash Anda, musuh dapat memaksa tabel hash Anda untuk membuat tabrakan, sangat menghambat kinerjanya. Solusinya adalah memilih fungsi hash secara acak dari keluarga, tetapi BST tidak memiliki kelemahan ini. Juga, ketika tekanan tabel hash tumbuh terlalu banyak, Anda sering cenderung memperbesar dan mengalokasikan kembali tabel hash yang mungkin merupakan operasi yang mahal. BST memiliki perilaku yang lebih sederhana di sini dan cenderung tidak mendadak mengalokasikan banyak data dan melakukan operasi pengulangan.
Pohon cenderung menjadi struktur data rata-rata tertinggi. Mereka dapat bertindak sebagai daftar, dapat dengan mudah dipecah untuk operasi paralel, memiliki penghapusan cepat, penyisipan dan pencarian dengan urutan O (lg n) . Mereka tidak melakukan apa pun dengan sangat baik, tetapi mereka juga tidak memiliki perilaku yang terlalu buruk.
Akhirnya, BST jauh lebih mudah diimplementasikan dalam bahasa fungsional (murni) dibandingkan dengan tabel hash dan mereka tidak memerlukan update destruktif untuk diimplementasikan ( argumen persistensi oleh Pascal di atas).
sumber
BSTs are much easier to implement in (pure) functional languages compared to hash-tables
- Betulkah? Saya ingin belajar bahasa fungsional sekarang!Keuntungan utama pohon biner dibandingkan tabel hash adalah bahwa pohon biner memberi Anda dua operasi tambahan yang tidak dapat Anda lakukan (dengan mudah, cepat) dengan tabel hash
temukan elemen yang paling dekat dengan (tidak harus sama dengan) beberapa nilai kunci arbitrer (atau paling dekat di atas / di bawah)
mengulangi isi pohon dalam urutan yang diurutkan
Keduanya terhubung - pohon biner menjaga isinya dalam urutan yang diurutkan, sehingga hal-hal yang memerlukan urutan yang diurutkan itu mudah dilakukan.
sumber
Pohon pencarian biner (seimbang) juga memiliki keuntungan karena kompleksitas asimtotiknya sebenarnya adalah batas atas, sedangkan waktu "konstan" untuk tabel hash adalah waktu diamortisasi: Jika Anda memiliki fungsi hash yang tidak sesuai, Anda dapat mengalami penurunan ke waktu linier , bukan konstan.
sumber
Sebuah hashtable akan mengambil lebih banyak ruang saat pertama kali dibuat - itu akan memiliki slot yang tersedia untuk elemen yang belum dimasukkan (apakah mereka pernah dimasukkan atau tidak), pohon pencarian biner hanya akan sebesar yang dibutuhkan menjadi. Selain itu, ketika tabel hash membutuhkan lebih banyak ruang, memperluas ke struktur lain bisa memakan waktu, tetapi itu mungkin tergantung pada implementasinya.
sumber
Pohon pencarian biner dapat diimplementasikan dengan antarmuka persisten , di mana pohon baru dikembalikan tetapi pohon lama tetap ada. Diimplementasikan dengan hati-hati, pohon lama dan baru berbagi sebagian besar node mereka. Anda tidak dapat melakukan ini dengan tabel hash standar.
sumber
Pohon biner lebih lambat untuk dicari dan disisipkan, tetapi memiliki fitur yang sangat bagus dari infix traversal yang pada dasarnya berarti Anda dapat melakukan iterasi melalui simpul pohon dalam urutan yang diurutkan.
Iterasi melalui entri tabel hash tidak masuk akal karena semuanya tersebar di memori.
sumber
Dari Cracking the Coding Interview, Edisi ke-6
Kita dapat mengimplementasikan tabel hash dengan pohon pencarian biner seimbang (BST). Ini memberi kita waktu pencarian O (log n). Keuntungannya adalah menggunakan lebih sedikit ruang, karena kita tidak lagi mengalokasikan larik yang besar. Kami juga dapat melakukan iterasi melalui kunci secara berurutan, yang terkadang berguna.
sumber
BST juga menyediakan operasi "findPredecessor" dan "findSuccessor" (Untuk menemukan elemen terkecil dan terbesar berikutnya) dalam waktu O (logn), yang mungkin juga merupakan operasi yang sangat berguna. Tabel Hash tidak dapat memberikan efisiensi waktu itu.
sumber
Jika Anda ingin mengakses data dengan cara yang disortir, maka daftar yang diurutkan harus dipertahankan secara paralel dengan tabel hash. Contoh yang bagus adalah Kamus dalam .Net. (lihat http://msdn.microsoft.com/en-us/library/3fcwy8h6.aspx ).
Ini memiliki efek samping tidak hanya memperlambat penyisipan, tetapi juga menghabiskan jumlah memori yang lebih besar daripada b-tree.
Selanjutnya, karena b-tree diurutkan, sangat mudah untuk menemukan rentang hasil, atau melakukan penggabungan atau penggabungan.
sumber
Itu juga tergantung pada penggunaan, Hash memungkinkan untuk menemukan kecocokan yang tepat. Jika Anda ingin meminta rentang maka BST adalah pilihannya. Misalkan Anda memiliki banyak data e1, e2, e3 ..... en.
Dengan tabel hash Anda dapat menemukan elemen apa pun dalam waktu yang konstan.
Jika Anda ingin menemukan nilai rentang yang lebih besar dari e41 dan kurang dari e8, BST dapat menemukannya dengan cepat.
Kuncinya adalah fungsi hash yang digunakan untuk menghindari tabrakan. Tentu saja, kami tidak dapat sepenuhnya menghindari tabrakan, dalam hal ini kami menggunakan perangkaian atau metode lain. Ini membuat waktu pengambilan tidak lagi konstan dalam kasus terburuk.
Setelah penuh, tabel hash harus meningkatkan ukuran keranjangnya dan menyalin semua elemen lagi. Ini adalah biaya tambahan yang tidak melebihi BST.
sumber
Tabel Hash tidak bagus untuk pengindeksan. Saat Anda mencari rentang, BST lebih baik. Itulah alasan mengapa kebanyakan indeks database menggunakan pohon B + daripada Tabel Hash
sumber
Pohon penelusuran biner adalah pilihan yang baik untuk mengimplementasikan kamus jika kunci memiliki beberapa urutan total (kunci sebanding) yang ditentukan padanya dan Anda ingin menyimpan informasi urutan.
Karena BST mempertahankan informasi pesanan, BST memberi Anda empat operasi set dinamis tambahan yang tidak dapat dilakukan (secara efisien) menggunakan tabel hash. Operasi ini adalah:
Semua operasi ini seperti setiap operasi BST memiliki kompleksitas waktu O (H). Selain itu, semua kunci yang disimpan tetap diurutkan di BST sehingga memungkinkan Anda untuk mendapatkan urutan kunci yang diurutkan hanya dengan melintasi pohon secara berurutan.
Singkatnya jika yang Anda inginkan hanyalah operasi penyisipan, hapus dan hapus maka tabel hash tidak terkalahkan (sebagian besar waktu) dalam kinerja. Tetapi jika Anda menginginkan salah satu atau semua operasi yang tercantum di atas, Anda harus menggunakan BST, sebaiknya BST yang menyeimbangkan diri.
sumber
Keuntungan utama dari tabel hash adalah ia melakukan hampir semua operasi di ~ = O (1). Dan sangat mudah untuk dipahami dan diterapkan. Itu memecahkan banyak "masalah wawancara" secara efisien. Jadi jika Anda ingin memecahkan wawancara pengkodean, bertemanlah dengan baik dengan tabel hash ;-)
sumber
Hashmap adalah array asosiatif set. Jadi, larik nilai input Anda dikumpulkan ke dalam beberapa keranjang. Dalam skema pengalamatan terbuka, Anda memiliki penunjuk ke keranjang, dan setiap kali Anda menambahkan nilai baru ke dalam keranjang, Anda mengetahui di mana dalam keranjang ada ruang kosong. Ada beberapa cara untuk melakukan ini - Anda mulai di awal bucket dan menaikkan penunjuk setiap kali dan menguji apakah sudah terisi. Ini disebut probing linier. Kemudian, Anda dapat melakukan penelusuran biner seperti menambahkan, di mana Anda menggandakan perbedaan antara awal keranjang dan tempat Anda menggandakan atau mundur setiap kali Anda mencari ruang kosong. Ini disebut probing kuadrat. BAIK. Sekarang masalah di kedua metode ini adalah jika bucket meluap ke alamat bucket berikutnya, Anda perlu-
BAIK. tetapi jika Anda menggunakan linkedlist seharusnya tidak ada masalah seperti itu bukan? Ya, Dalam daftar tertaut Anda tidak mengalami masalah ini. Mempertimbangkan setiap keranjang untuk memulai dengan daftar tertaut, dan jika Anda memiliki 100 elemen dalam satu keranjang, Anda harus melintasi 100 elemen tersebut untuk mencapai akhir linkedlist, maka List.add (Elemen E) akan membutuhkan waktu untuk-
Keuntungan dari implementasi linkedlist adalah Anda tidak memerlukan operasi alokasi memori dan transfer / copy O (N) dari semua bucket seperti dalam kasus implementasi pengalamatan terbuka.
Jadi, cara untuk meminimalkan operasi O (N) adalah dengan mengubah implementasi ke Binary Search Tree di mana operasi find adalah O (log (N)) dan Anda menambahkan elemen pada posisinya berdasarkan nilainya. Fitur tambahan dari BST adalah ia sudah diurutkan!
sumber
Pohon pencarian biner bisa lebih cepat bila digunakan dengan kunci string. Apalagi saat stringnya panjang.
Pohon pencarian biner menggunakan perbandingan untuk kurang / lebih besar yang cepat untuk string (bila tidak sama). Jadi BST dapat dengan cepat menjawab ketika string tidak ditemukan. Ketika sudah ditemukan itu hanya perlu melakukan satu perbandingan penuh.
Di tabel hash. Anda perlu menghitung hash dari string dan ini berarti Anda harus melalui semua byte setidaknya sekali untuk menghitung hash. Kemudian lagi, ketika entri yang cocok ditemukan.
sumber