Python neden kırmızı-siyah ağaç değil dikteyi uygulamak için hash tablosunu kullanıyor?
Anahtar nedir? Verim?
Python neden kırmızı-siyah ağaç değil dikteyi uygulamak için hash tablosunu kullanıyor?
Anahtar nedir? Verim?
Yanıtlar:
Bu, Python'a özgü olmayan genel bir cevaptır.
| 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.
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 == b
ve 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.
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:
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.
Doğru olabilecek bir dizi neden vardır , ancak kilit olanlar muhtemelen olasıdır:
Yazımı / bakımı daha kolay ve tipik kullanım durumlarında bir performans kazananı? Kaydol beni, lütfen!