В чем разница между SortedList и SortedDictionary? - PullRequest
246 голосов
/ 01 июня 2009

Есть ли реальная практическая разница между SortedList<TKey,TValue> и SortedDictionary<TKey,TValue>? Есть ли какие-то обстоятельства, когда вы бы специально использовали один, а не другой?

Ответы [ 7 ]

281 голосов
/ 01 июня 2009

Да - их рабочие характеристики существенно различаются. Вероятно, было бы лучше назвать их SortedList и SortedTree, поскольку это более точно отражает реализацию.

Посмотрите документы MSDN для каждого из них (SortedList, SortedDictionary) для получения подробных сведений о производительности для различных операций в различных ситуациях. Вот хорошее резюме (из SortedDictionary документов):

SortedDictionary<TKey, TValue> универсальный класс представляет собой двоичное дерево поиска с O (log n) поиск, где n - это количество элементов в словаре. В этом он похож на SortedList<TKey, TValue> универсальный учебный класс. Два класса имеют похожие объектные модели, и обе имеют O (log n) поиск. Где два класса отличаются использованием памяти и скоростью вставка и удаление:

  • SortedList<TKey, TValue> использует меньше памяти, чем SortedDictionary<TKey, TValue>.

  • SortedDictionary<TKey, TValue> имеет более быстрая вставка и удаление операции для несортированных данных, O (log n) в отличие от O (n) для SortedList<TKey, TValue>.

  • Если список заполнен сразу из отсортированных данных, SortedList<TKey, TValue> быстрее, чем SortedDictionary<TKey, TValue>.

(SortedList фактически поддерживает отсортированный массив, а не использует дерево. Он все еще использует бинарный поиск для поиска элементов.)

96 голосов
/ 21 мая 2014

Вот табличное представление, если это помогает ...

С производительности перспективы:

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

С реализации перспективы:

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

К примерно Перефразировать, если вам требуется грубая производительность, SortedDictionary может быть лучшим выбором. Если вам требуется меньше памяти и индексированный поиск, то SortedList подходит лучше. См. Этот вопрос для получения дополнительной информации о том, когда использовать который.

Вы можете прочитать больше здесь , здесь , здесь , здесь и здесь .

21 голосов
/ 23 февраля 2013

Я взломал Reflector, чтобы взглянуть на это, так как кажется, что SortedList немного сбит с толку. На самом деле это не двоичное дерево поиска, это отсортированный (по ключу) массив пар ключ-значение . Существует также переменная TKey[] keys, которая сортируется синхронно с парами ключ-значение и используется для двоичного поиска.

Вот некоторый источник (нацеленный на .NET 4.5) для резервного копирования моих заявлений.

Личные участники

// 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++;
}
13 голосов
/ 01 июня 2009

Проверьте страницу MSDN для SortedList :

Из раздела «Замечания»:

Универсальный класс SortedList<(Of <(TKey, TValue>)>) представляет собой двоичное дерево поиска с извлечением O(log n), где n - количество элементов в словаре. В этом он похож на универсальный класс SortedDictionary<(Of <(TKey, TValue>)>). Два класса имеют похожие объектные модели, и оба имеют O(log n) поиск. Различаются два класса в использовании памяти и скорости вставки и удаления:

  • SortedList<(Of <(TKey, TValue>)>) использует меньше памяти, чем SortedDictionary<(Of <(TKey, TValue>)>).
  • SortedDictionary<(Of <(TKey, TValue>)>) имеет более быстрые операции вставки и удаления несортированных данных, O(log n) вместо O(n) для SortedList<(Of <(TKey, TValue>)>).

  • Если список заполняется сразу из отсортированных данных, SortedList<(Of <(TKey, TValue>)>) быстрее, чем SortedDictionary<(Of <(TKey, TValue>)>).

11 голосов
/ 30 мая 2014

Это визуальное представление о том, как спектакли сравниваются друг с другом.

7 голосов
/ 06 июня 2016

На эту тему уже сказано достаточно, но, если говорить проще, вот мое мнение.

Сортированный словарь следует использовать, когда -

  • Требуются дополнительные операции вставки и удаления.
  • Данные в неупорядоченном виде.
  • Доступ к ключу достаточен, и индексный доступ не требуется.
  • Память не является узким местом.

С другой стороны, Сортированный список следует использовать, когда -

  • Требуется больше поисков и меньше операций вставки и удаления.
  • Данные уже отсортированы (если не все, большинство).
  • Требуется указатель доступа.
  • Память - это накладные расходы.

Надеюсь, это поможет !!

0 голосов
/ 15 ноября 2014

Индекс доступа (упомянутый здесь) является практической разницей. Если вам нужен доступ к преемнику или предшественнику, вам нужен SortedList. SortedDictionary не может этого сделать, поэтому вы довольно ограничены в том, как вы можете использовать сортировку (first / foreach).

...