it-swarm.com.de

Was ist der Unterschied zwischen SortedList und SortedDictionary?

Gibt es einen wirklichen praktischen Unterschied zwischen a SortedList<TKey,TValue> und ein SortedDictionary<TKey,TValue> ? Gibt es Umstände, unter denen Sie das eine und nicht das andere konkret einsetzen würden?

247
Shaul Behr

Ja - ihre Leistungsmerkmale unterscheiden sich erheblich. Es wäre wahrscheinlich besser, sie SortedList und SortedTree zu nennen, da dies die Implementierung genauer widerspiegelt.

In den MSDN-Dokumenten zu den einzelnen Vorgängen ( SortedList , SortedDictionary ) finden Sie Details zur Leistung für verschiedene Vorgänge in verschiedenen Situationen. Hier ist eine nette Zusammenfassung (aus den SortedDictionary Dokumenten):

Das SortedDictionary<TKey, TValue> generic class ist ein binärer Suchbaum mit O (log n) -Abfrage, wobei n die Anzahl der Elemente im Wörterbuch ist. In diesem ist es ähnlich wie die SortedList<TKey, TValue> Gattungsklasse. Die beiden Klassen haben ähnliche Objektmodelle und beide haben O (log n) -Abfrage. Wo sich die beiden Klassen unterscheiden, hängt von der Speichernutzung und der Geschwindigkeit des Einfügens und Entfernens ab:

  • SortedList<TKey, TValue> verbraucht weniger Speicher als SortedDictionary<TKey, TValue>.

  • SortedDictionary<TKey, TValue> hat schnellere Einfüge- und Entfernungsvorgänge für unsortierte Daten, O (log n) im Gegensatz zu O(n) für SortedList<TKey, TValue>.

  • Wenn die Liste gleichzeitig mit sortierten Daten gefüllt ist, wird SortedList<TKey, TValue> ist schneller als SortedDictionary<TKey, TValue>.

(SortedList verwaltet tatsächlich ein sortiertes Array, anstatt einen Baum zu verwenden. Es verwendet weiterhin die binäre Suche, um Elemente zu finden.)

283
Jon Skeet

Hier ist eine tabellarische Ansicht, wenn es hilft ...

Aus einer Performance-Perspektive :

+------------------+---------+----------+--------+----------+----------+---------+
| Collection       | Indexed | Keyed    | Value  | Addition |  Removal | Memory  |
|                  | lookup  | lookup   | lookup |          |          |         |
+------------------+---------+----------+--------+----------+----------+---------+
| SortedList       | O(1)    | O(log n) | O(n)   | O(n)*    | O(n)     | Lesser  |
| SortedDictionary | n/a     | O(log n) | O(n)   | O(log n) | O(log n) | Greater |
+------------------+---------+----------+--------+----------+----------+---------+

* Insertion is O(1) for data that are already in sort order, so that each 
  element is added to the end of the list (assuming no resize is required).

Aus einer Implementierungsperspektive :

+------------+---------------+----------+------------+------------+------------------+
| Underlying | Lookup        | Ordering | Contiguous | Data       | Exposes Key &    |
| structure  | strategy      |          | storage    | access     | Value collection |
+------------+---------------+----------+------------+------------+------------------+
| 2 arrays   | Binary search | Sorted   | Yes        | Key, Index | Yes              |
| BST        | Binary search | Sorted   | No         | Key        | Yes              |
+------------+---------------+----------+------------+------------+------------------+

Um ungefähr umzudrehen, wenn Sie rohe Leistung benötigen, könnte SortedDictionary eine bessere Wahl sein. Wenn Sie weniger Arbeitsspeicher benötigen und den indizierten Abruf durchführen möchten, ist SortedList besser geeignet. In dieser Frage erfahren Sie, wann Sie welche verwenden müssen.

Sie können mehr lesen hier , hier , hier , hier und hier .

97
nawfal

Ich habe Reflector aufgeschlagen, um mir das anzuschauen, da es ein bisschen Verwirrung um SortedList zu geben scheint. Es ist in der Tat kein binärer Suchbaum, es ist ein sortiertes (nach Schlüssel) Array von Schlüssel-Wert-Paaren. Da ist auch ein TKey[] keys Variable, die synchron mit den Schlüssel-Wert-Paaren sortiert und für die binäre Suche verwendet wird.

Hier ist eine Quelle (mit Ausrichtung auf .NET 4.5), um meine Ansprüche zu sichern.

Private Mitglieder

// Fields
private const int _defaultCapacity = 4;
private int _size;
[NonSerialized]
private object _syncRoot;
private IComparer<TKey> comparer;
private static TKey[] emptyKeys;
private static TValue[] emptyValues;
private KeyList<TKey, TValue> keyList;
private TKey[] keys;
private const int MaxArrayLength = 0x7fefffff;
private ValueList<TKey, TValue> valueList;
private TValue[] values;
private int version;

SortedList.ctor (IDictionary, IComparer)

public SortedList(IDictionary<TKey, TValue> dictionary, IComparer<TKey> comparer) : this((dictionary != null) ? dictionary.Count : 0, comparer)
{
    if (dictionary == null)
    {
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.dictionary);
    }
    dictionary.Keys.CopyTo(this.keys, 0);
    dictionary.Values.CopyTo(this.values, 0);
    Array.Sort<TKey, TValue>(this.keys, this.values, comparer);
    this._size = dictionary.Count;
}

SortedList.Add (TKey, TValue): void

public void Add(TKey key, TValue value)
{
    if (key == null)
    {
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
    }
    int num = Array.BinarySearch<TKey>(this.keys, 0, this._size, key, this.comparer);
    if (num >= 0)
    {
        ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_AddingDuplicate);
    }
    this.Insert(~num, key, value);
}

SortedList.RemoveAt (int): void

public void RemoveAt(int index)
{
    if ((index < 0) || (index >= this._size))
    {
        ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_Index);
    }
    this._size--;
    if (index < this._size)
    {
        Array.Copy(this.keys, index + 1, this.keys, index, this._size - index);
        Array.Copy(this.values, index + 1, this.values, index, this._size - index);
    }
    this.keys[this._size] = default(TKey);
    this.values[this._size] = default(TValue);
    this.version++;
}
21
Daniel Imms

Überprüfen Sie die MSDN-Seite für SortedList :

Aus dem Abschnitt "Bemerkungen":

Die generische Klasse SortedList<(Of <(TKey, TValue>)>) ist ein binärer Suchbaum mit O(log n) Abruf, wobei n die Anzahl der Elemente im Wörterbuch ist. In diesem Fall ähnelt es der generischen Klasse SortedDictionary<(Of <(TKey, TValue>)>). Die beiden Klassen haben ähnliche Objektmodelle und beide haben O(log n) Retrieval. Wo sich die beiden Klassen unterscheiden, hängt von der Speichernutzung und der Geschwindigkeit des Einfügens und Entfernens ab:

  • SortedList<(Of <(TKey, TValue>)>) belegt weniger Speicher als SortedDictionary<(Of <(TKey, TValue>)>).
  • SortedDictionary<(Of <(TKey, TValue>)>) hat schnellere Einfüge- und Entfernungsoperationen für unsortierte Daten, O(log n) im Gegensatz zu O(n) für SortedList<(Of <(TKey, TValue>)>).

  • Wenn die Liste gleichzeitig mit sortierten Daten gefüllt ist, ist SortedList<(Of <(TKey, TValue>)>) schneller als SortedDictionary<(Of <(TKey, TValue>)>).

13
Stephan

Dies ist eine visuelle Darstellung des Leistungsvergleichs.

11
Lev

Es ist bereits genug zu dem Thema gesagt, aber um es einfach zu halten, hier ist meine Ansicht.

Sortiertes Wörterbuch sollte verwendet werden, wenn-

  • Weitere Einfüge- und Löschvorgänge sind erforderlich.
  • Daten sind nicht bestellt.
  • Der Schlüsselzugriff ist ausreichend und ein Indexzugriff ist nicht erforderlich.
  • Speicher ist kein Engpass.

Auf der anderen Seite sollte Sorted List verwendet werden, wenn-

  • Es sind mehr Suchvorgänge und weniger Einfüge- und Löschvorgänge erforderlich.
  • Die Daten sind bereits sortiert (wenn nicht alle, die meisten).
  • Indexzugriff ist erforderlich.
  • Speicher ist ein Overhead.

Hoffe das hilft!!

8

Der Indexzugriff (hier erwähnt) ist der praktische Unterschied. Wenn Sie auf den Nachfolger oder Vorgänger zugreifen müssen, benötigen Sie SortedList. SortedDictionary kann das nicht, so dass Sie ziemlich eingeschränkt sind, wie Sie die Sortierung verwenden können (first/foreach).

0
Guy