Python neden kırmızı-siyah ağaç değil dikteyi uygulamak için hash tablosunu kullanıyor? [kapalı]


11

Python neden kırmızı-siyah ağaç değil dikteyi uygulamak için hash tablosunu kullanıyor?

Anahtar nedir? Verim?


2
Araştırmanızı paylaşmak herkese yardımcı olur . Neyi denediğinizi ve neden ihtiyaçlarınızı karşılamadığını bize bildirin. Bu, kendinize yardım etmeye zaman ayırdığınızı, bizi açık cevapları tekrar etmekten kurtardığını ve en önemlisi daha spesifik ve alakalı bir cevap almanıza yardımcı olduğunu gösteriyor. Ayrıca bkz. Nasıl
Sorulur

Yanıtlar:


16

Bu, Python'a özgü olmayan genel bir cevaptır.

Algoritmik karmaşıklık karşılaştırması

       | Hash Table  |   Red-Black Tree    |
-------+-------------+---------------------+
Space  | O(n) : O(n) | O(n)     : O(n)     |
Insert | O(1) : O(n) | O(log n) : O(log n) |
Fetch  | O(1) : O(n) | O(log n) : O(log n) |
Delete | O(1) : O(n) | O(log n) : O(log n) |
       | avg  :worst | average  : worst    |

Karma tablolarla ilgili sorun, karmaların çarpışabilmesidir. Çarpışmaları çözmek için çeşitli mekanizmalar vardır, örneğin açık adresleme veya ayrı zincirleme. Mutlak en kötü durum, tüm anahtarların aynı karma koduna sahip olmasıdır, bu durumda bir karma tablosu bağlantılı bir listeye düşer.

Diğer tüm durumlarda, bir karma tablosu, uygulanması kolay ve iyi performans sağlayan harika bir veri yapısıdır. Bir dezavantajı, tabloyu hızlı bir şekilde büyütebilecek ve girişlerini yeniden dağıtabilecek uygulamaların gerçekte kullanıldığı kadar bellek harcayacağıdır.

RB Ağaçları kendi kendini dengeliyorlar ve en kötü durumda algoritmik karmaşıklıklarını değiştirmiyorlar. Ancak, uygulanması daha zordur. Ortalama karmaşıklıkları da karma tablonunkinden daha kötüdür.

Tuşlardaki kısıtlamalar

Karma tablodaki tüm anahtarlar, birbirleri arasında eşitlik için yıkanabilir ve karşılaştırılabilir olmalıdır. Bu özellikle dizeler veya tamsayılar için kolaydır, ancak kullanıcı tanımlı türlere uzanmak da oldukça kolaydır. Java gibi bazı dillerde bu özellikler tanım gereği garanti edilmektedir.

Bir RB Ağacındaki anahtarların toplam sırası olmalıdır: her anahtar diğer anahtarlarla karşılaştırılabilir olmalı ve iki anahtar daha küçük, daha büyük veya eşit karşılaştırmalıdır. Bu düzen eşitliği anlamsal eşitliğe eşit olmalıdır. Bu, tamsayılar ve diğer sayılar için basittir, dizeler için de oldukça kolaydır (siparişin yalnızca tutarlı olması ve harici olarak gözlemlenebilir olması gerekmez, bu nedenle siparişin yerel ayarları dikkate alması gerekmez [1] ), ancak doğal düzeni olmayan diğer türler için zor . Aralarında bazı karşılaştırmalar mümkün olmadıkça, farklı türde tuşlara sahip olmak kesinlikle imkansızdır.

[1]: Aslında burada yanılıyorum. İki dize bayt-eşit olmayabilir ancak yine de bazı dilin kurallarına göre eşdeğer olabilir. İki eşit dizenin farklı şekilde kodlandığı bir örnek için bkz. Örneğin Unicode normalleştirmeleri. Karma anahtarınızın Unicode karakter kompozisyonunun önemli olup olmadığı, karma tablo uygulamasının bilemeyeceği bir şeydir.

RB-Tree anahtarları için ucuz bir çözümün önce eşitliği test etmek, daha sonra kimliği karşılaştırmak (yani işaretçileri karşılaştırmak) olabileceği düşünülebilir. Eğer: Ancak bu sıralama Geçişli olmaz a == bve id(a) > id(c)o zaman o uymalı id(b) > id(c)burada garanti edilmez hangi yanı. Bunun yerine, arama anahtarları olarak karma anahtar kodunu kullanabiliriz. Burada, sipariş doğru çalışır, ancak aynı karma koduna sahip RB ağacındaki aynı düğüme atanacak birden fazla ayrı anahtarla sonuçlanabilir. Bu karma çarpışmaları çözmek için, hash tablolarında olduğu gibi ayrı zincirleme kullanabiliriz, ancak bu aynı zamanda hash tabloları için en kötü durum davranışını - her iki dünyanın en kötüsü - miras alır.

Diğer görüşler

  • Bir karma tablo aslında bir dizi olduğundan, bir karma tablo bir ağaç daha iyi bellek yer olması bekliyorum.

  • Her iki veri yapısındaki girişler oldukça yüksek bir ek yüke sahiptir:

    • hash tablosu: ayrı zincirleme durumunda anahtar, değer ve sonraki giriş işaretçisi. Ayrıca karma kodunun saklanması yeniden boyutlandırmayı hızlandırabilir.
    • RB ağacı: anahtar, değer, renk, sol alt işaretçi, sağ alt işaretçi. Renk tek bir bit olsa da, hizalama sorunlarının neredeyse tüm bir işaretçi için veya yalnızca iki boyutlu bellek bloklarının gücü tahsis edilebildiğinde yaklaşık dört işaretçi için yeterli alan harcayacağınız anlamına gelebileceğini unutmayın. Her durumda, bir RB ağacı girdisi karma tablo girdisinden daha fazla bellek tüketir.
  • Bir RB ağacına ekleme ve silme işlemleri ağaç dönüşlerini içerir. Bunlar gerçekten pahalı değil, ama bir ek yük içeriyor. Bir karma içinde, ekleme ve silme basit bir erişimden daha pahalı değildir (ekleme sırasında bir karma tablosunun yeniden boyutlandırılması bir uğraştır O(n)).

  • Hash tabloları doğası gereği değişebilirken, RB ağacı da değişmez bir şekilde uygulanabilir. Ancak, bu nadiren yararlıdır.


Çarpışan karmaları için küçük RB ağaçlarıyla bir karma masamız olabilir mi?
aragaer

@aragaer genellikle değil, ancak bazı özel durumlarda mümkün olabilir. Bununla birlikte, çarpışmalar genellikle bağlantılı listelerle ele alınır - uygulanması çok daha kolay, daha az yük ve genellikle çok daha performanslı çünkü tipik olarak sadece çok az çarpışma var. Birçok çarpışma beklersek, karma işlevini değiştirebilir ya da daha basit bir B-ağacı kullanabiliriz. RB ağaçları gibi kendi kendini dengeleyen ağaçlar harika, ancak sadece değer katmadıkları birçok durum var.
amon

Ağaçların "<" değerini destekleyen nesnelere ihtiyacı vardır. Karma tablolar hash + "=" destekleyen nesnelere ihtiyaç duyar. Bu nedenle RB ağaçları mümkün olmayabilir. Ama gerçekten hash tablonuzda önemli miktarda çarpışma varsa, anahtarları çarpmak için alternatif bir algoritmaya değil, yeni bir hash fonksiyonuna ihtiyacınız var.
gnasher729

1

Doğru olabilecek bir dizi neden vardır , ancak kilit olanlar muhtemelen olasıdır:

  • Karma tabloları uygulamak ağaçlardan daha kolaydır. İkisi de tamamen önemsiz değil, ancak karma tabloları biraz daha kolay ve yasal anahtarların etki alanı üzerindeki etkisi, sadece bir karma işlevine ve bir eşitlik işlevine ihtiyacınız olduğu için daha az katıdır; ağaçlar tam bir sipariş fonksiyonu gerektirir ve bu yazmak çok daha zordur.
  • Karma tablolar küçük boyutlarda daha iyi performans gösterebilir. Bu çok önemlidir, çünkü işin önemli bir kısmı teorik olarak büyük veri kümeleriyle ilgilenir; pratikte, çoğu insan tarafından değil, sadece onlarca veya yüzlerce anahtarla çalışır. Küçük ölçekli performans çok önemlidir ve orada neyin en iyi olduğunu bulmak için asimptotik analizi kullanamazsınız; gerçekte uygulamak ve ölçmek zorundasınız.

Yazımı / bakımı daha kolay ve tipik kullanım durumlarında bir performans kazananı? Kaydol beni, lütfen!

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.