C # İkili Ağaçlar ve Sözlükler

oy
15

Ben ikili arama ağaçları ve ne zaman sözlükleri kullanmak ne zaman kullanılacağını kavramı ile mücadele ediyorum.

Benim uygulamada C5 kütüphanesini kullanılan küçük bir deney yaptım TreeDictionary(ben kırmızı-siyah ikili arama ağacı olduğuna inanıyoruz), ve C # sözlüğü. Sözlük / eklenti her zaman hızlıydı işlemleri bulup da hep daha az bellek alanı kullanılır. Örneğin, 16.809 at <int, float>girişleri, sözlük 723 KiB kullanılan ağacın ederken 342 KiB kullandı.

Ben BST en fazla bellek verimli olması gerekiyordu olduğunu düşündüm, ama ağacın bir düğümün sözlükte birden fazla giriş bayt gerektirdiğini görünüyor. Ne verir? BST en sözlüklerde daha iyi olduğu bir nokta var mı?

Depolamak için daha hızlı + daha fazla bellek verimli veri yapısı varsa da, bir yan soru olarak bilen var <int, float>sözü yapıların ikisinden de sözlük türü erişimi için çiftleri?

Oluştur 28/01/2010 saat 02:46
kaynak kullanıcı
Diğer dillerde...                            


6 cevaplar

oy
1

Bir erken optimizasyonu yapıyoruz gibi geliyor bana.

Ben sana ne öneririm bir arabirim aslında kullanmakta olduğunuz yapı ayırt edebilir ve ardından (en iyi iş gibi görünüyor) Sözlük kullanarak arabirim uygulamak yaratmaktır.

bellek / performans (muhtemelen 20k- numaraları için olacak), o zaman diğer arayüz uygulamaları oluşturmak ve en iyilerini işleri hangisinin kontrol edebilirsiniz bir sorunu haline gelirse. Sen kod (ki uygulama dışında kullandığınız) geri kalanında neredeyse her şeyi değiştirmeye gerek yoktur.

Cevap 28/01/2010 saat 03:26
kaynak kullanıcı

oy
1

Bu bir ağaç düğüm bir sözlük girişinin daha fazla depolama alanı gerektirir mantıklı geliyor. Bir ikili ağaç düğümü değeri ve hem sol ve sağ alt ağaçlar saklaması gerekir. Genel Dictionary<TKey, TValue>I varsayarak - - ya her bir bölüm (değer artı bir işaretçi / referans) ya da yeniden eşleme çeşit (sadece değeri) için bir bağlantılı liste kullanan bir karma tablo olarak uygulanır. Emin olmak için yansıtıcı içinde bir göz sahip olurdu, ancak bu sorunun amacıyla ben o kadar önemli olduğunu sanmıyorum.

seyrek karma tablo, depolama / bellek açısından daha az verimlidir. Eğer bir karma tablo (sözlük) oluşturmak ve 1 milyona kapasitesini başlatmak ve sadece 10.000 elemanları ile doldurmak, sonra da 10.000 düğümlerle bir BST çok daha fazla bellek yiyiyor olur eminim.

düğümleri / tuşları miktarı sadece bin ise Yine de, bunların hiçbirini dert olmaz. Yani fiziksel RAM gigabyte kıyasla kilobayt cinsinden ölçülecek gidiyor.


Sorunuz, "neden bir karma tablosu yerine bir ikili ağaç kullanmak isteyeyim?" karma tablo değildir oysa Sonra en iyi yanıtı IMO ikili ağaçlar sıralanır olmasıdır. Yalnızca bir şeye tam olarak eşit anahtarlar için bir karma tablo arama yapabilir; Bir ağacın, sen değer aralığına en yakın değere, vb bir dizin ya da benzer bir şey yaratmak eğer Bu oldukça önemli bir ayrımdır arayabilirsiniz.

Cevap 28/01/2010 saat 03:39
kaynak kullanıcı

oy
0

Bir Ağacı ve Hash tablo için arayüz çok benzer olmalıdır (Ben tahmin ediyorum senin Sözlük birini dayanmaktadır budur). Her zaman etrafında kilitlenmiştir aramalarını döner.

Hep bir sözlük kez şeyler yaratmak ve daha sonra bunun üzerine aramalarının çok yapıyor için daha iyi olduğunu düşündüm. Bir ağaç daha iyi iken önemli ölçüde değiştirerek sanki. Ben yukarı bu fikri aldı nereye Ancak, ben bilmiyorum.

(Fonksiyonel diller genellikle buna küçük değişiklikler yaparsanız ağacın en yeniden kullanabilirsiniz onlar koleksiyonları için temel olarak ağaçları kullanın).

Cevap 28/01/2010 saat 03:40
kaynak kullanıcı

oy
0

Bir BST size bir verecektir "elma ile elma" karşılaştırarak değil sipariş bir sözlük (sizin durumunuzda) Bir anahtar değeri çifti üzerinde arama yapmanızı sağlar iken temsilini.

Ben 2 arasında bellek ayak izi çok boyutunu şey istemem ama Sözlük size çok daha hızlı arama verecektir. Bir BST bir öğeyi bulmak için, (potansiyel olarak) tüm ağaç hareket etmesi gerekli. Ama bir dictnary arama yapmak için sadece anahtar dayanan arama.

Cevap 28/01/2010 saat 04:05
kaynak kullanıcı

oy
8

Ben BST en fazla bellek verimli olması gerekiyordu olduğunu düşündüm, ama ağacın bir düğümün sözlükte birden fazla giriş bayt gerektirdiğini görünüyor. Ne verir? BST en sözlüklerde daha iyi olduğu bir nokta var mı?

Ben şahsen böyle bir prensip duymadım. Hatta hala onun sadece genel bir ilke değil, bir kategorik gerçektir evrenin kumaş kazınmış.

Genellikle, Sözlükler bağlantılı listelerin bir dizi etrafında gerçekten sadece bir fantezi sarıcı bulunmaktadır. Sen gibi sözlük şey haline ekleyin:

LinkedList<Tuple<TKey, TValue>> list =
    internalArray[internalArray % key.GetHashCode()];
if (list.Exists(x => x.Key == key))
    throw new Exception("Key already exists");
list.AddLast(Tuple.Create(key, value));

Yani onun neredeyse O (1) işlemi. Sözlük n koleksiyonunda öğelerin sayısı O (internalArray.Length + n) bellek kullanır.

Genel BSTS olarak olarak uygulanabilir:

  • n, toplama sayı ürün O (n) alan kullanımı bağlı listeler.
  • diziler (2 Ç kullanmak, h saat ağacın yüksekliği ve n toplama öğe sayısı olduğu - N) yer.
    • Kırmızı-siyah ağaçlar O (1.44 * n) sınırlı bir yüksekliğe sahip olduğundan, bir dizi uygulama (yaklaşık 2 O sınırlı bir bellek kullanımı olmalıdır 1.44n - n)

Oran, C5 TreeDictionary muhtemelen boşa alan sorumludur diziler, kullanılarak uygulanır edilir.

Ne verir? BST en sözlüklerde daha iyi olduğu bir nokta var mı?

Sözlükleri bazı istenmeyen özelliklere sahiptir:

  • bellek gereksinimleri mevcut toplam RAM daha çok daha az olsa bile, sizin sözlüğü tutmak için bellek yeterli continugous bloklar olmayabilir.

  • Karma işlevi değerlendirilmesi bir zaman keyfi uzun boyunu alabilir. Dizeleri, örneğin, incelemek için Reflektör kullanmak System.String.GetHashCodeyöntemini - Bir dize karma fark edeceksiniz her zaman çok uzun dizeleri önemli bir zaman alabilir anlamına gelen O (n) zaman alır. Sadece ilk birkaç karakter bakarak gerektirebilir beri yandan, hemen hemen her zaman daha hızlı karma daha eşitsizlik için dizeleri karşılaştırma. Onun tamamen mümkün hash kodu değerlendirme çok uzun sürerse ağaç ekler Sözlük uçlar daha hızlı olması için.

    • Int32 en GetHashCodemetodu anlamıyla adildir return this, yani int tuşlarıyla bir hashtable bir ağaç sözlüğe daha yavaş olduğu bir durumda bulmak hardpressed olurdu.

RB Ağaçlar bazı istenilen özelliklere sahiptir:

  • Sen bir sözlük kullanarak O (n) süresi ile karşılaştırıldığında zaman (n log), / bulmak O'da Min ve Max öğelerini kaldırabilirsiniz.

  • Bir ağaç bağlantılı listeden ziyade bir dizi olarak uygulanırsa, ağaçtır genellikle bir sözlüğe daha verimli daha fazla yer.

  • Aynı şekilde, onun saçma kolay zaman (n log) O silmek / ekleme / arama desteklemek ağaçların değişmez versiyonlarını yazmak. Aslında, ben her operasyon için (tüm iç diziyi kopyalamanız gerekir çünkü Sözlükler, değişmezlik iyi uyum yok olan değişmez parmak ağaçları, genel amaçlı sözlük veri yapısının bir tür bazı dizi tabanlı uygulamaları görülen, ancak uygulaması çok olduğu kompleks).

  • Bir diziye bir karma tablo dökümü ve aynı etkiyi elde etmek için onu sıralamak gerekiyordu oysa, sürekli uzay ve O (n) zaman içinde sıralanmış sırayla bir ağaçta tüm unsurları geçebilirler.

Yani, veri yapısının seçimi gerçekten ihtiyacınız olanı özellikleri bağlıdır. Sadece bir sırasız çantayı istiyorum ve hash fonksiyonu hızlı bir şekilde değerlendirmek olduğunu garanti ederseniz, bir .Net Sözlük ile gitmek. Eğer sıralı bir çanta lazım veya yavaş koşu karma işlevi varsa, TreeDictionary ile gitmek.

Cevap 28/01/2010 saat 04:16
kaynak kullanıcı

oy
0

Eğer gecikme sivri ve karma çarpışmalar saldırılara karşı veri yapısını korumak için gerekiyorsa bir dengeli BST tercih edilir.

bir dizi destekli yapı, yeniden boyutlandırılmış alır büyür, ilkinin sondaki sınırlı tam sayı aralığı sonsuz alan bir çıkıntı olarak müzakere algoritmasının kaçınılmaz bir özelliktir, gerçekleşir.

.NET bir diğer sorun LOH ve yeterince büyük bir sözlükle bir LOH bölünmesi ile olmasıdır. Bu durumda daha büyük algoritmik karmaşıklık sınıfın bir fiyat ödeyerek, bir BST'yi kullanabilirsiniz.

Eğer O (K) en kötü durum zaman olsun hashtable'a ile Kısacası, tahsis yığın tarafından desteklenen bir BST ile sen, en kötü durum O (log (N)) zaman olsun.

BST O (log (N)) ortalama süre, kötü önbellek yerellik ve daha yığın ayırmaları bir bedeli, ancak gecikme garantileri vardır ve sözlük saldırıları ve bellek parçalanması korunmaktadır.

Worth BST de diğer platformlarda bellek parçalanması için bir konu olduğunu belirterek, bir sıkıştırma çöp toplayıcı kullanmıyor.

bir off-yığın bağlantılı liste gibi verileri depolayan değeri depolar ve ofset bilgilerini, bellek boyutu için olduğu gibi, .NET Dictionary`2 sınıfı, daha fazla bellek etkilidir. TSİ (her bir düğüm, bir sınıf örneği yığın üzerinde olduğu gibi), iki işaretleyicinin ve dengeli ağaç için bir arttırılmış ağaç veri nesnesi, başlığın depolanması için yer alır. Örneğin, kırmızı-siyah ağaç renk (kırmızı veya siyah) olarak yorumlanır bir boolean gerekir. Yanılmıyorsam, bu, en az 6 makine kelime. Yani, 64-bit sistemde kırmızı-siyah ağacın her düğüm bir minimumdur:

başlık = 24 bayt alt işaretçileri için 2 kelime = 16 bayt değerin 8+ bayt = 24 + 8 + 16 + 8 = 56 bayt için renk için 1 kelime = 8 byte en az 1 kelime için 3 kelime (+ 8 bayt ağacı) bir üst düğüm işaretçi kullanıyorsa.

Aynı zamanda, sözlük girdisinin minimum boyutu sadece 16 byte olacaktır.

Cevap 10/12/2018 saat 13:18
kaynak kullanıcı

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more