Keuntungan dari Pohon Pencarian Biner dibandingkan Tabel Hash


102

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.


untuk tabel hash berapa waktu berjalan untuk find () insert () dan remove ()? theta (1) theta (1) dan theta (1) kan?
Dikhususkan

8
Hampir selalu, ya. Jika Anda mengalami banyak tabrakan, waktu tersebut mungkin bertambah menjadi O (n).
Christian Mann

1
Waktu ini juga bergantung pada fungsi hashing Anda. Jika karena alasan yang aneh bukan O (1), jelas operasi Anda akan memiliki batas minimum efisiensi apa pun yang dijalankan oleh fungsi hash Anda.
Christian Mann

Saya akan mengatakan keuntungan terbesar dari BST adalah dalam struktur data yang diurutkan. Detail use case sudah tercantum di sini .
Yuantao

Jawaban:


93

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.


33
Tidak benar bahwa seluruh rentang keluaran fungsi hash harus ada dalam larik. Nilai hash dapat dengan mudah dimodifikasi oleh panjang array untuk memungkinkan array yang lebih kecil. Tentu saja, jumlah elemen terakhir yang ditambahkan mungkin tidak diketahui, jadi tabel hash mungkin masih mengalokasikan lebih banyak ruang daripada yang diperlukan. Pohon pencarian biner dapat menghabiskan banyak memori atau lebih. Implementasi tertaut membutuhkan ruang untuk setidaknya dua pointer tambahan per elemen (tiga jika menggunakan pointer induk), dan BST berbasis array dapat membuang banyak memori untuk bagian pohon yang tidak terisi.
Solaraeus

4
@Solaraeus: BST berbasis array adalah yang terbaik untuk dibandingkan dengan tabel hash dan tidak lebih boros daripada tabel hash. Anda juga dapat memperluas BST dengan lebih dari satu salinan memori, dibandingkan dengan menghitung ulang seluruh tabel.
Guvante

125

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)


11
BST melakukan pencarian jangkauan secara efisien! Bagi saya ini adalah jawaban terbaik dari segi pendekatan praktis dan algoritmik.
ady

4
wow ini benar-benar menjelaskan mengapa pohon sangat terkait dengan database; manfaatnya paling terlihat saat Anda perlu melakukan pemfilteran berbasis kunci. dengan peta hash, Anda perlu mengulang semua kunci untuk menyelesaikan "temukan semua item dengan kunci antara 1000 dan 3290"
Dmitry

77

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.


3
melintasi dalam urutan apa pun mungkin tidak masuk akal di hashtable.
FrustratedWithFormsDesigner


Terima kasih untuk tautannya, itu ide yang menarik! Saya tidak berpikir saya pernah melihat atau menggunakan implementasi dari itu (setidaknya tidak secara sadar).
FrustratedWithFormsDesigner


51

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).


3
BSTs are much easier to implement in (pure) functional languages compared to hash-tables- Betulkah? Saya ingin belajar bahasa fungsional sekarang!
nawfal

1
Tabel hash harus tetap ada dalam bahasa fungsional. Ini sering kali mempersulit implementasi.
SAYA MEMBERIKAN JAWABAN

untuk menguraikan, jika Anda membuat struktur data president dalam bahasa fungsional, yang akhirnya Anda lakukan hanyalah menulis kode yang sama seperti yang Anda lakukan di assembly, kecuali dalam setiap operasi Anda secara eksplisit mengubah array memori / register Anda, atau berbicara dengan server untuk berpura-pura untuk melakukannya. Saya semua menyadari keadaan Anda tetapi itu isomorfik untuk pendekatan imperatif jika dilakukan dengan benar (Anda tidak dapat secara realistis menyalin sejumlah besar data pada setiap transformasi dalam kehidupan nyata, Anda perlu menipu).
Dmitry

27

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.


BST menemukan kecocokan terdekat, hanya jika kecocokan persisnya tidak ada, bukan? Bagaimana jika Anda menemukan kecocokan tepat di root itu sendiri?
developer747

2
@ developer747: Kemudian yang terdekat berikutnya di bawah dan di atas adalah daun paling kanan dari subtree kiri dan daun paling kiri dari subtree kanan.
Chris Dodd

16

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.


3
Untuk mengarahkan poin ini ke rumah, kasus yang merosot adalah ketika koleksi berisi banyak salinan hanya dari 1 kunci. di BST, masukkan adalah O (log n), dalam tabel Hash, masukkan adalah O (n)
SingleNegationElimination

2
Ketika tabel hash berisi banyak salinan hanya dari 1 kunci, sisipkan adalah (masih) O (1), bukan O (n). Masalah untuk tabel hash adalah ketika ada banyak kunci berbeda dengan hash yang sama. Hal ini dapat dihindari dengan skema hash dinamis yang beralih ke fungsi hash yang berbeda ketika terjadi banyak benturan.
Chris Dodd

Catatan dari pohon yang tidak seimbang dapat merosot menjadi daftar dan juga memiliki pencarian O (n).
awiebe

9

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.


8

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.


6

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.


6

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.


5

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.


Jika Anda mencari operasi "findPredecessor" dan "findSuccessor", maka HashTable adalah pilihan yang buruk untuk struktur data.
AKDesai

1

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.


1

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.


1

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


indeks database adalah dari kedua jenis pohon hash dan B +. Ketika Anda ingin melakukan perbandingan seperti lebih besar dari atau kurang dari, maka indeks pohon B + berguna jika Indeks hash berguna untuk pencarian. Juga pikirkan ketika data tidak sebanding dan jika u ingin membuat indeks, maka db akan membuat indeks hash dan bukan indeks pohon B +. @ssD
Singh

1

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:

  1. Maksimum
  2. Minimum
  3. Penerus
  4. Pendahulu

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.


0

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 ;-)


Saya pikir OP meminta keuntungan dari BST dibandingkan hashing.
Sniper

0

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-

  1. Gandakan setiap ukuran bucket- malloc (N bucket) / ubah fungsi hash- Waktu yang dibutuhkan: bergantung pada implementasi malloc
  2. Transfer / Salin setiap data bucket sebelumnya ke data bucket baru. Ini adalah operasi O (N) di mana N mewakili keseluruhan data

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-

  1. Hash elemen ke bucket- Normal seperti di semua implementasi
  2. Luangkan waktu untuk menemukan elemen terakhir dalam operasi bucket-O (N) tersebut.

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!


0

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.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.