SortedList <>, SortedDictionary <> ve Dictionary <>


Yanıtlar:


102
  1. İkisinden birindeki öğeler üzerinde yinelendiğinde, öğeler sıralanacaktır. Öyle değil Dictionary<T,V>.

  2. MSDN , SortedList<T,V>ve SortedDictionary<T,V>aşağıdakiler arasındaki farkı ele alır :

SortedDictionary (TKey, TValue) genel sınıfı, O (log n) alımına sahip ikili bir arama ağacıdır ; burada n, sözlükteki öğelerin sayısıdır. Bu açıdan SortedList (TKey, TValue) genel sınıfına benzer. İki sınıfın benzer nesne modelleri vardır ve her ikisinin de O (log n) alımı vardır. İki sınıfın farklı olduğu yerlerde bellek kullanımı ve ekleme ve çıkarma hızı söz konusudur:

SortedList (TKey, TValue) SortedDictionary'den (TKey, TValue) daha az bellek kullanır.

SortedDictionary (TKey, TValue), sıralanmamış veriler için daha hızlı ekleme ve kaldırma işlemlerine sahiptir: SortedList (TKey, TValue) için O (n) yerine O (log n).

Liste sıralanan verilerden aynı anda doldurulursa, SortedList (TKey, TValue) SortedDictionary (TKey, TValue) 'den daha hızlıdır.


21
Diğer bir pratik fark, SortedListindekse göre geri alabilmeniz (anahtarla geri almanın aksine) ve yapamamanızdır SortedDictionary.
Andrew Savinykh

67

görüntü açıklamasını buraya girin

Sözlükler arasındaki farktan bahsedeceğim.

Yukarıdaki resim, bunun Dictionary<K,V>her durumda Sortedanaloğa eşit veya daha hızlı olduğunu göstermektedir , ancak öğelerin sırası gerekirse, örneğin bunları yazdırmak için, Sortedbiri seçilir.

Src: http://people.cs.aau.dk/~normark/oop-csharp/html/notes/collections-note-time-complexity-dictionaries.html


1
Mükemmel genel bakış. Orijinal soruda olmasa da Immutable, bu sözlüklerin sürümleri arasında seçim yaparsanız , Sortedsürümlerin aslında sıralanmamış muadillerinden% 40-50 daha hızlı olduğu (yine de O(log(n)), ancak işlem başına belirgin şekilde daha hızlı) not edilmelidir. . Zamanlamalar, girişin nasıl sıralanacağına bağlı olarak değişebilir. Bkz stackoverflow.com/a/30638592/111575
Abel

22

Bir Performans Testinin sonuçlarını özetlemek için - SortedList - SortedDictionary - Dictionary - Hashtable , farklı senaryolar için en iyiden en kötüye doğru sonuçlar:

Hafıza kullanımı:

SortedList<T,T>
Hashtable
SortedDictionary<T,T>
Dictionary<T,T>

Eklemeler:

Dictionary<T,T>
Hashtable
SortedDictionary<T,T>
SortedList<T,T>

Arama İşlemleri:

Hashtable
Dictionary<T,T>
SortedList<T,T>
SortedDictionary<T,T>

foreach döngü işlemleri

SortedList<T,T>
Dictionary<T,T>
Hashtable
SortedDictionary<T,T>

1
Bu test sonuçları incelenirken SortedDictionary'nin varoluş nedeni sorgulanabilir .
beawolf

1
Senin Eğer Collectionihtiyaçları olduğu sortedkonusunda o zaman unutabilir Hashtableve Dictionary> SortedList gitmek ama bekledikleri zaman sık sık gerekecektir - Eğer bir çekimde sizin Koleksiyonu doldurmak eğer: .Addve .Removeöğeleri -> SortedDictionary için gidin.
Ama

Belki de ne sortedanlama geldiğini açıklığa kavuşturmaya ihtiyaç vardır : öğeleri For Each MyItem in Collectionorijinal olarak düzenlediğiniz sırayla işlenmek yerine, bunları değerler üzerindeki kriterlere göre bir sırayla işleyecektir ( a'da tanımlanan ). Örneğin, Anahtarlarınız Dizeler ise, Koleksiyonunuz varsayılan olarak Anahtarlarınızın alfabetik sırasına göre işlenir, ancak her zaman özel bir sıralama kuralı tanımlayabilirsiniz. .Addsorted CollectionKeyIComparer
Ama

10

Önerilen cevapların performansa odaklandığını görebiliyorum. Aşağıda verilen makale performansla ilgili yeni bir şey sağlamaz, ancak temeldeki mekanizmaları açıklar. Ayrıca Collection, soruda belirtilen üç Türe odaklanmadığını , ancak System.Collections.Genericad alanının tüm Türlerini ele aldığını unutmayın .

http://geekswithblogs.net/BlackRabbitCoder/archive/2011/06/16/c.net-fundamentals-choosing-the-right-collection-class.aspx

Özler:

Sözlük <>

Sözlük, muhtemelen en çok kullanılan ilişkisel kapsayıcı sınıfıdır. Sözlük, kapakların altında bir karma tablo kullandığı için ilişkili aramalar / eklemeler / silmeler için en hızlı sınıftır . Anahtarlar karma hale getirildiğinden, anahtar türü GetHashCode () ve Equals () 'ı doğru şekilde uygulamalı veya inşa sırasında sözlüğe harici bir IEqualityComparer sağlamalısınız. Sözlükteki öğelerin ekleme / silme / arama süresi amortize edilmiş sabit zamandır - O (1) - bu, sözlük ne kadar büyük olursa olsun, bir şeyi bulmak için geçen sürenin nispeten sabit kaldığı anlamına gelir. Bu, yüksek hızlı aramalar için oldukça arzu edilir. Tek dezavantajı , karma tablo kullanmanın doğası gereği sözlüğün sırasız olmasıdır.Sözlükteki öğeleri sırayla kolayca gezemezsiniz .

SortedDictionary <>

SortedDictionary, kullanım açısından Sözlüğe benzer, ancak uygulamada çok farklıdır. SortedDictionary anahtar tarafından sırayla öğeleri korumak için yorganın altında bir ikili ağacı kullanır . Sıralamanın bir sonucu olarak , anahtar için kullanılan tür , anahtarların doğru şekilde sıralanabilmesi için IComparable'ı doğru şekilde uygulamalıdır . Sıralanan sözlük, öğeleri sırayla muhafaza etme yeteneği için biraz arama süresiyle işlem yapar, bu nedenle sıralı bir sözlüğe ekleme / silme / arama süreleri logaritmik - O (log n) şeklindedir. Genel olarak konuşursak, logaritmik zamanla, koleksiyonun boyutunu ikiye katlayabilirsiniz ve öğeyi bulmak için yalnızca bir ekstra karşılaştırma yapması gerekir. Hızlı aramalar istediğinizde ancak aynı zamanda koleksiyonu anahtara göre sırayla koruyabilmek istediğinizde SortedDictionary kullanın.

SortedList <>

SortedList, genel kapsayıcılardaki diğer sıralanmış ilişkisel kapsayıcı sınıfıdır. SortedDictionary gibi SortedList, anahtar / değer çiftlerini sıralamak için bir anahtar kullanır . Ancak SortedDictionary'den farklı olarak, SortedList'teki öğeler sıralı öğe dizisi olarak saklanır.. Bu, ekleme ve silmelerin doğrusal olduğu anlamına gelir - O (n) - çünkü bir öğeyi silmek veya eklemek listedeki tüm öğeleri yukarı veya aşağı kaydırmayı içerebilir. Bununla birlikte, arama süresi O (log n) 'dir çünkü SortedList, listedeki herhangi bir öğeyi anahtarına göre bulmak için ikili bir arama kullanabilir. Öyleyse neden bunu yapmak isteyesiniz? Cevap şu ki, SortedList'i önceden yükleyecekseniz, eklemeler daha yavaş olacaktır, ancak dizi indeksleme aşağıdaki nesne bağlantılarından daha hızlı olduğu için aramalar marjinal olarak SortedDictionary'den daha hızlıdır. Bir kez daha bunu, hızlı aramalar istediğiniz ve koleksiyonu anahtara göre sırayla korumak istediğiniz ve ekleme ve silme işlemlerinin nadir olduğu durumlarda kullanacağım.


Temel Prosedürlerin Geçici Özeti

Her şeyi doğru anlamadığımdan emin olduğum için geri bildirim çok açıktır.

  • Tüm diziler boyuttadır n.
  • Sıralanmamış dizi = .Ekle /. Kaldır O (1), ancak. Öğe (i) O (n).
  • Sıralanmış dizi = .Ekle /. Kaldır O (n), ancak .Item (i) O (log n).

Sözlük

Hafıza

KeyArray(n) -> non-sorted array<pointer>
ItemArray(n) -> non-sorted array<pointer>
HashArray(n) -> sorted array<hashvalue>

Ekle

  1. HashArray(n) = Key.GetHash# O (1) ekle
  2. KeyArray(n) = PointerToKey# O (1) ekle
  3. ItemArray(n) = PointerToItem# O (1) ekle

Kaldırmak

  1. For i = 0 to n, inerede HashArray(i) = Key.GetHash # O (log n) (sıralanmış dizi) bulun
  2. Kaldır HashArray(i)# O (n) (sıralanmış dizi)
  3. KeyArray(i)# O (1) öğesini kaldır
  4. ItemArray(i)# O (1) öğesini kaldır

Ürünü Al

  1. For i = 0 to n, inerede HashArray(i) = Key.GetHash# O (log n) (sıralanmış dizi) bulun
  2. Dönüş ItemArray(i)

Döngü

  1. For i = 0 to n, dönüş ItemArray(i)

SortedDictionary

Hafıza

KeyArray(n) = non-sorted array<pointer>
ItemArray(n) = non-sorted array<pointer>
OrderArray(n) = sorted array<pointer>

Ekle

  1. KeyArray(n) = PointerToKey# O (1) ekle
  2. ItemArray(n) = PointerToItem# O (1) ekle
  3. For i = 0 to n, inerede KeyArray(i-1) < Key < KeyArray(i)(kullanarak ICompare) # O (n)
  4. OrderArray(i) = n# O (n) (sıralanmış dizi) ekle

Kaldırmak

  1. For i = 0 to n, inerede KeyArray(i).GetHash = Key.GetHash# O (n) bulun
  2. KeyArray(SortArray(i))# O (n) öğesini kaldır
  3. ItemArray(SortArray(i))# O (n) öğesini kaldır
  4. Kaldır OrderArray(i)# O (n) (sıralanmış dizi)

Ürünü Al

  1. For i = 0 to n, inerede KeyArray(i).GetHash = Key.GetHash# O (n) bulun
  2. Dönüş ItemArray(i)

Döngü

  1. For i = 0 to n, dönüş ItemArray(OrderArray(i))

Sıralanmış Liste

Hafıza

KeyArray(n) = sorted array<pointer>
ItemArray(n) = sorted array<pointer>

Ekle

  1. For i = 0 to n, inerede KeyArray(i-1) < Key < KeyArray(i)(kullanarak ICompare) # O (log n) bulun
  2. KeyArray(i) = PointerToKey# O (n) ekle
  3. ItemArray(i) = PointerToItem# O (n) ekle

Kaldırmak

  1. For i = 0 to n, inerede KeyArray(i).GetHash = Key.GetHash# O (log n) bulun
  2. KeyArray(i)# O (n) öğesini kaldır
  3. ItemArray(i)# O (n) öğesini kaldır

Ürünü Al

  1. For i = 0 to n, inerede KeyArray(i).GetHash = Key.GetHash# O (log n) bulun
  2. Dönüş ItemArray(i)

Döngü

  1. For i = 0 to n, dönüş ItemArray(i)

9
  1. Koleksiyonun üzerinde yinelediğinizde anahtara göre sıralanmasını istediğinizde. Verilerinizin sıralanmasına ihtiyacınız yoksa, sadece bir Sözlük kullanmanız daha iyi olur, daha iyi performansa sahip olur.

  2. SortedList ve SortedDictionary hemen hemen aynı şeyi yapar, ancak farklı şekilde uygulanır, bu nedenle burada açıklanan farklı güçlü ve zayıf yönlere sahiptir .


0

@Lev tarafından sunulan her vakaya bir performans puanı atamaya çalışırken , aşağıdaki değerleri kullandım:

  • O (1) = 3
  • O (günlük n) = 2
  • O (n) = 1
  • O (1) veya O (n) = 2
  • O (log n) veya O (n) = 1.5

Sonuçlar (daha yüksek = daha iyi):

Dictionary:       12.0 
SortedDictionary:  9.0 
SortedList:        6.5

Elbette her kullanım durumu belirli işlemlere daha fazla ağırlık verecektir.


1
Genel bir kural olarak, O (log n) 'nin ağırlığı log (n) / log (2) (her n ikiye katlandığında +1) olurken, O (n)' nin ağırlığı n olacaktır. Yani ağırlıklandırmanız 4'e kadar olan bedenler için doğru olacaktır. Bunun ötesinde herhangi bir şey 2: 1 oranınızın hızla yükseldiğini görecektir. Örneğin n = 100 ise, O (log n) = 15 olmalıdır. Benzer bir düşünceye göre, O (1) değeriniz 100'dür. Sonuç: O (n) savaşı oldukça hızlı kaybeder. Aksi takdirde, dizinizin küçük olduğu ve bu durumda verimliliğin bir sorun olmadığı anlamına gelir.
Ama
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.