Qual è la differenza tra SortedList e SortedDictionary?


261

C'è qualche reale differenza pratica tra a SortedList<TKey,TValue>e a SortedDictionary<TKey,TValue>? Ci sono circostanze in cui useresti specificamente l'una e non l'altra?



13
Non ho capito bene. Perché SortedList ha due parametri di tipo SortedList<TKey,TValue>anziché uno SortedList<T>? Perché non implementa IList<T>?
Colonnello Panic,

3
@ColonelPanic perché funzionalmente SortedList è una mappa, non una raccolta lineare. Non lasciarti ingannare dal nome. Proprio come un dizionario, si passa una chiave, si ottiene un valore indietro. Mentre il dizionario non è ordinato, SortedList è ordinato nel suo ordinamento naturale.
nawfal,

Risposte:


294

Sì, le loro caratteristiche prestazionali differiscono in modo significativo. Probabilmente sarebbe meglio chiamarli SortedListeSortedTree poiché ciò riflette l'attuazione più da vicino.

Guarda i documenti MSDN per ciascuno di essi ( SortedList, SortedDictionary) per i dettagli delle prestazioni per diverse operazioni in diverse situtations. Ecco un bel riassunto (dai SortedDictionarydocumenti):

La SortedDictionary<TKey, TValue>classe generica è un albero di ricerca binario con recupero O (log n), dove n è il numero di elementi nel dizionario. In questo, è simile alla SortedList<TKey, TValue>classe generica. Le due classi hanno modelli di oggetti simili ed entrambe hanno il recupero O (log n). Dove le due classi differiscono è nell'uso della memoria e nella velocità di inserimento e rimozione:

  • SortedList<TKey, TValue>usa meno memoria di SortedDictionary<TKey, TValue>.

  • SortedDictionary<TKey, TValue>ha operazioni di inserimento e rimozione più veloci per dati non ordinati, O (log n) rispetto a O (n) per SortedList<TKey, TValue>.

  • Se l'elenco viene popolato tutto in una volta da dati ordinati, SortedList<TKey, TValue>è più veloce di SortedDictionary<TKey, TValue>.

( SortedListmantiene effettivamente un array ordinato, anziché utilizzare un albero. Utilizza ancora la ricerca binaria per trovare gli elementi.)


Grazie mille a tutti per i suggerimenti. Immagino di essere troppo pigro con RTFM ... molto più facile chiedere alle brave persone su SO ...;) Ho votato entrambi per le risposte; Jon ottiene credito per essere stato il primo a scattare. :)
Shaul Behr,

2
Penso che la definizione di SortedList dovrebbe essere corretta in quanto non credo che sia un albero di ricerca binario ...?
nchaud,

1
Ho cercato con reflector e ho scoperto che non utilizzava un albero di ricerca binario.
Daniel Imms,

Penso che Sorteddictionary sia un albero AVL o Red-Blacktree (tutti i costi di operazione O (logn). E la SortedList è una ricerca binaria (costa o (n) tempo nel peggiore dei casi) l
Ghoster

105

Ecco una vista tabulare se aiuta ...

Dal punto di vista delle prestazioni :

+------------------+---------+----------+--------+----------+----------+---------+
| 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).

Dal punto di vista dell'implementazione :

+------------+---------------+----------+------------+------------+------------------+
| 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              |
+------------+---------------+----------+------------+------------+------------------+

Per circa parafrasi, se avete bisogno di prestazioni pure SortedDictionarypotrebbe essere una scelta migliore. Se è necessario un minore sovraccarico di memoria e il recupero indicizzato si SortedListadatta meglio. Vedi questa domanda per maggiori informazioni su quando usare quale.

Puoi leggere di più qui , qui , qui , qui e qui .


Nota che se desideri buone prestazioni e un utilizzo della memoria relativamente basso e il recupero indicizzato, considera BDictionary<Key,Value>in LoycCore invece che SortedDictionary.
Qwertie,

1
Sì, guarda la parte inferiore di questo articolo . Si scopre che di BDictionarysolito è più lento rispetto ad SortedDictionaryeccezione di dimensioni molto grandi, ma è più veloce che SortedListse ci sono oltre 700 articoli o giù di lì. L'uso della memoria dovrebbe essere solo leggermente più alto di SortedList(molto più basso di SortedDictionary), a causa dell'uso di matrici nelle foglie dell'albero.
Qwertie,

22

Ho aperto Reflector per dare un'occhiata a questo dato che sembra esserci un po 'di confusione SortedList. In realtà non è un albero di ricerca binario, è un array ordinato (per chiave) di coppie chiave-valore . C'è anche unTKey[] keys variabile che viene ordinata in sincronia con le coppie chiave-valore e utilizzata per la ricerca binaria.

Ecco alcune fonti (destinate a .NET 4.5) per il backup delle mie richieste.

Membri privati

// 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): vuoto

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++;
}

13

Dai un'occhiata alla pagina MSDN per SortedList :

Dalla sezione Osservazioni:

La SortedList<(Of <(TKey, TValue>)>)classe generica è un albero di ricerca binario con O(log n)recupero, dove nè il numero di elementi nel dizionario. In questo, è simile alla SortedDictionary<(Of <(TKey, TValue>)>)classe generica. Le due classi hanno modelli di oggetti simili ed entrambi hanno il O(log n)recupero. Dove le due classi differiscono è nell'uso della memoria e nella velocità di inserimento e rimozione:

  • SortedList<(Of <(TKey, TValue>)>)usa meno memoria di SortedDictionary<(Of <(TKey, TValue>)>).
  • SortedDictionary<(Of <(TKey, TValue>)>)ha operazioni di inserimento e rimozione più veloci per dati non ordinati, O(log n)al contrario di O(n)per SortedList<(Of <(TKey, TValue>)>).

  • Se l'elenco viene popolato tutto in una volta dai dati ordinati, SortedList<(Of <(TKey, TValue>)>)è più veloce di SortedDictionary<(Of <(TKey, TValue>)>).


9
Il testo tra virgolette è errato (ed è stato aggiornato su MSDN): SortedList non è un "albero di ricerca binario", è un "array di coppie chiave / valore".
Eldritch Conundrum,

12

Questa è una rappresentazione visiva di come le prestazioni si confrontano tra loro.


Da dove hai preso quelle informazioni? Da questo schema possiamo vedere che Dictinary è meglio in ogni modo, quindi non c'è motivo per l'esistenza di altri.
alex kostin,

9

È già stato detto abbastanza sull'argomento, tuttavia per semplificarlo, ecco la mia opinione.

Dizionario ordinato dovrebbe essere usato quando-

  • Sono necessari più inserimenti ed operazioni di eliminazione.
  • Dati non ordinati.
  • L'accesso alle chiavi è sufficiente e non è richiesto l'accesso all'indice.
  • La memoria non è un collo di bottiglia.

Dall'altro lato, l' elenco ordinato dovrebbe essere usato quando-

  • Sono necessarie più ricerche e meno inserimenti ed operazioni di eliminazione.
  • I dati sono già ordinati (se non tutti, la maggior parte).
  • È richiesto l'accesso all'indice.
  • La memoria è un sovraccarico.

Spero che questo ti aiuti!!


1

L'accesso all'indice (menzionato qui) è la differenza pratica. Se è necessario accedere al successore o al predecessore, è necessario SortedList. SortedDictionary non può farlo, quindi sei abbastanza limitato su come utilizzare l'ordinamento (primo / foreach).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.