İkili Arama Ağaçlarının Karma Tablolara Göre Avantajları


104

İkili arama ağaçlarının karma tablolara göre avantajları nelerdir?

Karma tablolar, Theta (1) zamanındaki herhangi bir öğeyi arayabilir ve bir öğe eklemek kadar kolaydır ... ancak bunun tersi olan avantajlardan emin değilim.


karma tablolar için find () insert () ve remove () için çalışma süreleri nelerdir? teta (1) teta (1) ve teta (1) değil mi?
Sadık

8
Neredeyse her zaman, evet. Çok fazla çarpışmayla karşılaşırsanız, bu zamanlar O (n) 'ye kadar çıkabilir.
Christian Mann

1
Bu zamanlar aynı zamanda karma işlevinize de bağlıdır. Garip bir nedenden ötürü O (1) değilse, açıkçası işlemlerinizin hash fonksiyonunuzun çalıştığı verimlilik için minimum bir sınırı olacaktır.
Christian Mann

BST'nin en büyük avantajı sıralı bir veri yapısında olmasıdır. Ayrıntılı kullanım durumu burada zaten listelenmiştir .
Yuantao

Yanıtlar:


93

İkili Arama Ağaçlarının (referans tabanlı) bellek açısından verimli olduğunu unutmayın. İhtiyaç duyduklarından daha fazla bellek ayırmazlar.

Örneğin, bir karma işlevinin bir aralığı R(h) = 0...100varsa, sadece 20 öğeye hashing yapıyor olsanız bile, 100 (işaretçilerden) öğelerden oluşan bir dizi ayırmanız gerekir. Aynı bilgileri depolamak için bir ikili arama ağacı kullanacak olsaydınız, yalnızca ihtiyaç duyduğunuz kadar alanı ve bağlantılar hakkında bazı meta verileri ayırırdınız.


33
Karma işlevi çıktılarının tüm aralığının dizide bulunması gerektiği doğru değildir. Hash değerleri, daha küçük bir diziye izin vermek için basitçe dizinin uzunluğu ile değiştirilebilir. Tabii ki, eklenen elemanların nihai sayısı bilinmeyebilir, bu nedenle karma tablo yine de gerekenden daha fazla alan tahsis edebilir. İkili arama ağaçları da aynı miktarda veya daha fazlasını boşa harcayabilir. Bağlantılı uygulamalar, öğe başına en az iki ek işaretçi için alana ihtiyaç duyar (ana işaretçi kullanılıyorsa üç) ve dizi tabanlı BST'ler, ağacın doldurulmamış bölümleri için çok fazla bellek harcayabilir.
Solaraeus

4
@Solaraeus: Dizi tabanlı BST'ler, karma tablolarla karşılaştırmak için en iyisidir ve karma tablolardan daha fazla israf değildir. Ayrıca, tüm tabloyu yeniden hesaplamaya kıyasla bir bellek kopyasından biraz daha fazlasını içeren bir BST'yi genişletebilirsiniz.
Guvante

127

Hiç kimsenin belirtmediği bir avantaj, ikili arama ağacının verimli bir şekilde aralık aramaları yapmanıza izin vermesidir.

Fikrimi açıklamak için, aşırı bir örnek vermek istiyorum. Anahtarları 0 ile 5000 arasında olan tüm öğeleri almak istediğinizi varsayalım. Ve aslında bu türden yalnızca bir öğe ve anahtarları aralıkta olmayan 10000 başka öğe vardır. BST, yanıt almanın imkansız olduğu bir alt ağaçta arama yapmadığı için, aralık aramalarını oldukça verimli bir şekilde yapabilir.

Bir karma tabloda aralık aramalarını nasıl yapabilirsiniz? Ya O (n) olan her kova alanını yinelemeniz gerekir, ya da 1,2,3,4… 'den 5000'e kadar her birinin var olup olmadığına bakmanız gerekir. (0 ile 5000 arasındaki tuşlar sonsuz bir kümedir? örneğin anahtarlar ondalık sayı olabilir)


11
BST'ler, aralık aramalarını verimli bir şekilde yapar! Benim için bu, pratik ve algoritmik yaklaşım açısından en iyi cevap.
ady

4
vay bu gerçekten ağaçların veritabanlarıyla neden bu kadar ilişkili olduğunu açıklıyor; faydaları en çok anahtar tabanlı filtreleme yapmanız gerektiğinde görünür. karma haritalar ile, "1000 ile 3290 arasındaki tüm öğeleri bul" çözmek için tüm anahtarların üzerinden geçmeniz gerekir
Dmitry

77

İkili ağacın bir "avantajı", tüm öğeleri sırayla listelemek için üzerinden geçilebilmesidir. Bu bir Hash tablosu ile imkansız değildir, ancak hash uygulanmış bir yapıya tasarım olarak normal bir işlem değildir.


3
Herhangi bir sırada gezinmek, muhtemelen bir hashtable'da bir anlam ifade etmeyecektir.
FrustratedWithFormsDesigner

2
@FrustratedWithFormsDesigner. Bkz Sıralama Doğrusal Hash Tablosu
NealB

Bağlantı için teşekkürler, bu kesişen bir fikir! Bunun bir uygulamasını hiç gördüğümü veya kullandığımı sanmıyorum (en azından bilerek değil).
FrustratedWithFormsDesigner

1

51

Diğer tüm iyi yorumlara ek olarak:

Karma tablolar genel olarak, ikili ağaçlara kıyasla daha az bellek okuması gerektiren daha iyi önbellek davranışına sahiptir. Bir karma tablo için, verilerinizi tutan bir referansa erişmeden önce normalde yalnızca tek bir okumaya maruz kalırsınız. İkili ağaç, dengeli bir varyant ise, k * lg (n) bellek okumaları için bazı sabit k'ler için bir şey gerektirir .

Öte yandan, bir düşman hash fonksiyonunuzu bilirse, hash masanızı çarpışmalar yapmaya zorlayarak performansını büyük ölçüde bozabilir. Çözüm, karma işlevini bir aileden rastgele seçmektir, ancak BST'nin bu dezavantajı yoktur. Ayrıca, karma tablo basıncı çok arttığında, genellikle pahalı bir işlem olabilecek karma tabloyu büyütme ve yeniden tahsis etme eğilimindesinizdir. BST'nin burada daha basit davranışı vardır ve aniden çok fazla veri tahsis etme ve yeniden düzenleme işlemi yapma eğiliminde değildir.

Ağaçlar, nihai ortalama veri yapısı olma eğilimindedir. Liste olarak hareket edebilir, paralel işlem için kolayca bölünebilir, O (lg n) sırasına göre hızlı çıkarma, ekleme ve arama yapabilir . Hiçbir şeyi özellikle iyi yapmazlar , ancak aşırı derecede kötü davranışları da yoktur.

Son olarak, BST'lerin (saf) işlevsel dillerde uygulanması, karma tablolara kıyasla çok daha kolaydır ve yıkıcı güncellemelerin uygulanmasını gerektirmez ( yukarıdaki Pascal'ın kalıcılık argümanı).


3
BSTs are much easier to implement in (pure) functional languages compared to hash-tables- Gerçekten mi? Şimdi işlevsel bir dil öğrenmek istiyorum!
nawfal

1
Karma tablonun işlevsel bir dilde kalıcı olması gerekir. Bu genellikle uygulamaları zorlaştırır.
CRAP CEVAPLARI

ayrıntılı olarak açıklamak gerekirse, eğer başkan veri yapılarını işlevsel dillerde yaparsanız, gerçekten yapmanız gereken tek şey, her işlemde bellek / kayıt dizinizi açık bir şekilde dönüştürmeniz veya bir sunucuyla rol yapıp bunu yapmak için. Durumunuzun farkında olduğum için varım, ancak doğru yapılırsa zorunlu yaklaşıma izomorfiktir (gerçek yaşamdaki her dönüşümle ilgili büyük miktarda veriyi gerçekçi bir şekilde kopyalayamazsınız, hile yapmanız gerekir).
Dmitry

27

Bir ikili ağacın bir karma tabloya göre ana avantajları, ikili ağacın size bir karma tablo ile yapamayacağınız (kolay ve hızlı bir şekilde) iki ek işlem vermesidir.

  • Bazı rastgele anahtar değerlerine (veya en yakın yukarı / aşağı) en yakın (eşit olması gerekmez) öğeyi bulun

  • Ağacın içeriğini sıralı bir şekilde yineleyin

İkisi birbirine bağlıdır - ikili ağaç, içeriğini sıralı bir sırayla saklar, böylece sıralı sırayı gerektiren şeyler yapmak kolaydır.


BST en yakın eşleşmeyi bulur, ancak tam eşleşme yoksa, değil mi? Ya kökün kendisinde tam bir eşleşme bulursanız?
developer747

2
@ developer747: Ardından, bir sonraki en yakın alt ağacın en sağdaki yaprağı ve sağ alt ağacın en soldaki yaprağıdır.
Chris Dodd

16

Bir (dengeli) ikili arama ağacı, asimptotik karmaşıklığının aslında bir üst sınır olması avantajına da sahiptir, oysa karma tablolar için "sabit" zamanlar amortize edilmiş zamanlardır: Uygun olmayan bir hash fonksiyonunuz varsa, doğrusal zamana indirgenebilirsiniz. sabit değil.


3
Bu noktayı eve götürmek için, dejenere bir durum, koleksiyonun sadece 1 anahtarın birçok kopyasını içerdiği durumdur. BST'de, insert O (log n), bir Hash tablosunda, insert is O (n)
SingleNegationElimination,

2
Bir karma tablo sadece 1 anahtarın birçok kopyasını içerdiğinde, ekleme (hala) O (1), O (n) değil. Karma tablolar için sorun , aynı karma değerine sahip birçok farklı anahtarın olmasıdır. Bu, birçok çarpışma olduğunda farklı bir hash fonksiyonuna geçen dinamik bir hash şemasıyla önlenebilir.
Chris Dodd

Dengesiz bir ağacın bir listeye dönüşebileceğine ve ayrıca O (n) aramasına sahip olabileceğine dikkat edin.
awiebe

9

Bir hashtable, ilk oluşturulduğunda daha fazla yer kaplar - henüz eklenecek olan öğeler için kullanılabilir yuvalara sahip olur (eklenmiş olsun ya da olmasın), bir ikili arama ağacı yalnızca ihtiyaç duyduğu kadar büyük olacaktır. olmak. Bir karma-tablo fazla oda ihtiyaç duyduğunda Ayrıca, başka yapıya genişleyen olabilir zaman alıcı olabilir, ama bu uygulamaya bağlı olabilir.


8

İkili bir arama ağacı, yeni bir ağacın döndürüldüğü ancak eski ağacın varlığını sürdürdüğü kalıcı bir arayüzle gerçekleştirilebilir. Dikkatli bir şekilde uygulandığında, eski ve yeni ağaçlar düğümlerinin çoğunu paylaşır. Bunu standart bir karma tablo ile yapamazsınız.


6

İkili bir ağacın aranması ve eklenmesi daha yavaştır, ancak iç içe geçmenin çok güzel bir özelliğine sahiptir, bu da temelde ağacın düğümleri arasında sıralı bir sırayla yineleme yapabileceğiniz anlamına gelir.

Bir karma tablonun girişlerini yinelemek pek bir anlam ifade etmiyor çünkü hepsi hafızaya dağılmış durumda.


6

Gönderen Kodlama Röportajı Cracking, 6th Edition

Hash tablosunu dengeli bir ikili arama ağacı (BST) ile uygulayabiliriz. Bu bize bir O (log n) arama süresi verir. Bunun avantajı, artık büyük bir dizi ayırmadığımız için potansiyel olarak daha az alan kullanmaktır. Ayrıca anahtarları sırayla yineleyebiliriz, bu bazen yararlı olabilir.


5

BST'ler aynı zamanda O (logn) zamanında "findPredecessor" ve "findSuccessor" işlemlerini (sonraki en küçük ve sonraki en büyük elemanları bulmak için) sağlar ve bu da çok kullanışlı işlemler olabilir. Hash Table o zaman verimliliğini sağlayamaz.


"FindPredecessor" ve "findSuccessor" işlemlerini arıyorsanız, HashTable ilk etapta veri yapısı için kötü bir seçimdir.
AKDesai

1

Verilere sıralı bir şekilde erişmek istiyorsanız, karma tabloya paralel olarak sıralı bir listenin korunması gerekir. İyi bir örnek .Net'teki Sözlük'tir. (bkz. http://msdn.microsoft.com/en-us/library/3fcwy8h6.aspx ).

Bu, yalnızca eklemeleri yavaşlatmakla kalmaz, aynı zamanda bir b-ağacından daha fazla miktarda bellek tüketir.

Ayrıca, bir b-ağacı sıralandığı için, sonuç aralıklarını bulmak veya birleştirme veya birleştirme yapmak kolaydır.


1

Aynı zamanda kullanıma da bağlıdır, Hash tam eşleşmeyi bulmaya izin verir. Bir aralık için sorgulama yapmak istiyorsanız, seçim BST'dir. Bir çok veriniz olduğunu varsayalım e1, e2, e3 ..... tr.

Karma tablo ile herhangi bir elemanı sabit zamanda bulabilirsiniz.

E41'den büyük ve e8'den küçük aralık değerlerini bulmak isterseniz, BST bunu hızlı bir şekilde bulabilir.

Önemli olan, bir çarpışmayı önlemek için kullanılan hash fonksiyonudur. Elbette bir çarpışmadan tamamen kaçınamayız, bu durumda zincirleme veya başka yöntemlere başvururuz. Bu, en kötü durumlarda geri çağırmanın artık sabit zaman olmasını sağlamaz.

Dolduktan sonra, hash tablosunun kova boyutunu artırması ve tüm öğeleri tekrar kopyalaması gerekir. Bu, BST üzerinde bulunmayan ek bir maliyettir.


1

Karma Tablolar indeksleme için iyi değildir. Bir aralık ararken, BST'ler daha iyidir. Çoğu veritabanı dizininin Karma Tablolar yerine B + ağaçlarını kullanmasının nedeni budur.


veritabanları indeksleri hem karma hem de B + ağaç türlerindendir. Şundan büyük veya küçük gibi karşılaştırma yapmak istediğinizde, B + ağaç indeksi kullanışlıdır, aksi halde hash İndeksi arama için kullanışlıdır. Ayrıca, verilerin karşılaştırılabilir olmadığı ve indeks oluşturmak istediğinizde, db B + ağaç indeksi değil, hash indeksi oluşturacaktır. @ssD
Sukhmeet Singh

1

İkili arama ağaçları, anahtarların üzerinde tanımlanmış bir toplam sıraya (anahtarlar karşılaştırılabilir) sahipse ve sipariş bilgilerini korumak istiyorsanız, sözlüğü uygulamak için iyi bir seçimdir.

BST, sipariş bilgilerini koruduğu için, size hash tabloları kullanılarak (verimli bir şekilde) gerçekleştirilemeyen dört ek dinamik ayar işlemi sağlar. Bu işlemler şunlardır:

  1. Maksimum
  2. Minimum
  3. Halef
  4. Selef

Her BST işleminde olduğu gibi tüm bu işlemler, O (H) 'nin zaman karmaşıklığına sahiptir. Ek olarak, saklanan tüm anahtarlar BST'de sıralı olarak kalır, böylece sırayla ağacı geçerek sıralı anahtar dizisini elde etmenizi sağlar.

Özetle, tek istediğiniz işlem ekleme, silme ve kaldırma ise, hash tablosu performansta (çoğu zaman) rakipsizdir. Ancak, yukarıda listelenen işlemlerden herhangi birini veya tümünü istiyorsanız, bir BST, tercihen kendi kendini dengeleyen bir BST kullanmalısınız.


0

Hash tablosunun ana avantajı, ~ = O (1) 'deki hemen hemen tüm opları yapmasıdır. Anlaması ve uygulaması çok kolaydır. Birçok "görüşme problemini" verimli bir şekilde çözer. Eğer bir kodlama röportajı kırmak istiyorsanız, hash table ;-) ile en iyi arkadaşlar edinin.


Bence OP, hashing yerine BST'nin avantajlarını istedi.
Sniper

0

Bir hashmap, küme bir ilişkilendirilebilir dizidir. Dolayısıyla, girdi değerleri diziniz kümeler halinde havuzlanır. Açık bir adresleme şemasında, bir kova için bir işaretçiniz vardır ve bir kovaya her yeni bir değer eklediğinizde, kova içinde nerede boş alanlar olduğunu öğrenirsiniz. Bunu yapmanın birkaç yolu vardır - bölümün başlangıcından başlar ve her seferinde işaretçiyi artırır ve dolu olup olmadığını test edersiniz. Buna doğrusal problama denir. Ardından, bölmenin başlangıcı ile boş bir alan ararken her seferinde ikiye katladığınız veya geri aldığınız yer arasındaki farkı ikiye katladığınız add gibi ikili bir arama yapabilirsiniz. Buna ikinci dereceden araştırma denir. TAMAM. Şimdi bu iki yöntemdeki sorun şu ki, eğer paket sonraki paket adreslerine taşarsa, o zaman yapmanız gereken-

  1. Her bir kova boyutunu ikiye katlayın - malloc (N kova) / karma işlevini değiştirin - Gereken süre: malloc uygulamasına bağlıdır
  2. Önceki grup verilerinin her birini yeni grup verilerine aktarın / kopyalayın. Bu, N'nin tüm verileri temsil ettiği bir O (N) işlemidir

TAMAM. ama bağlantılı bir liste kullanırsanız böyle bir sorun olmamalı değil mi? Evet, bağlantılı listelerde bu problem yok. Her bir grubun bağlantılı bir listeyle başladığını düşünürsek ve bir pakette 100 öğe varsa, bağlantılı listenin sonuna ulaşmak için bu 100 öğeyi geçmeniz gerekir, dolayısıyla List.add (E Öğesi) zaman alacaktır.

  1. Öğeyi bir pakete karma - Tüm uygulamalarda olduğu gibi Normal
  2. Bahsedilen kova-O (N) işleminde son elemanı bulmak için zaman ayırın.

Bağlantılı liste uygulamasının avantajı, açık adresleme uygulamasında olduğu gibi bellek ayırma işlemine ve tüm paketlerin O (N) aktarımına / kopyasına ihtiyacınız olmamasıdır.

Bu nedenle, O (N) işlemini en aza indirmenin yolu, uygulamayı bulma işlemlerinin O (log (N)) olduğu bir İkili Arama Ağacına dönüştürmektir ve öğeyi değerine göre konumuna eklersiniz. Bir BST'nin eklenen özelliği, sıralı olarak gelmesidir!


0

İkili arama ağaçları, dize anahtarlarıyla kullanıldığında daha hızlı olabilir. Özellikle dizeler uzun olduğunda.

Dizeler için hızlı olan (eşit olmadıklarında) daha az / daha büyük karşılaştırmaları kullanan ikili arama ağaçları. Böylece bir BST, bir dizi bulunamadığında hızlı bir şekilde yanıt verebilir. Bulunduğunda yalnızca bir tam karşılaştırma yapması gerekecektir.

Bir hash tablosunda. Dizenin karmasını hesaplamanız gerekir ve bu, karmayı hesaplamak için tüm baytlardan en az bir kez geçmeniz gerektiği anlamına gelir. Sonra yine eşleşen bir giriş bulunduğunda.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.