Яка різниця між SortedList та SortedDictionary?


261

Чи є реальна практична різниця між a SortedList<TKey,TValue>і a SortedDictionary<TKey,TValue>? Чи є обставини, коли ви спеціально використовували б одне, а не друге?



13
Я збентежений. Чому SortedList має два типи параметрів, SortedList<TKey,TValue>а не один SortedList<T>? Чому він не реалізується IList<T>?
Полковник Паніка

3
@ColonelPanic, оскільки функціонально SortedList - це карта, а не лінійна колекція. Не дозволяйте, щоб ім’я вас обдурило. Подібно до словника, ви вводите ключ, отримуєте значення назад. Поки словник є не упорядкованим, сортується список упорядкований у природному відсортованому порядку.
nawfal

Відповіді:


294

Так - їх експлуатаційні характеристики суттєво відрізняються. Напевно, було б краще їх назвати, SortedListі SortedTreeце відображає реалізацію більш ретельно.

Перегляньте документи MSDN для кожного з них ( SortedList, SortedDictionary) для отримання детальної інформації про ефективність для різних операцій у різних ситуаціях. Ось приємний підсумок (з SortedDictionaryдокументів):

SortedDictionary<TKey, TValue>Загальний клас являє собою бінарне дерево пошуку з O (журнал п) вилучення, де п число елементів в словнику. У цьому вона схожа на 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насправді підтримує відсортований масив, а не дерево. Він все ще використовує двійковий пошук для пошуку елементів.)


Велике спасибі всім за покажчики. Я думаю, що я занадто ледачий на RTFM ... набагато простіше запитати приємних людей на ТАК ...;) Я проголосував за вас обох за відповіді; Джон отримує кредит на відповідь за те, що був першим на спуску. :)
Shaul Behr

2
Я думаю, що визначення SortedList слід виправити, оскільки я не вірю, що це бінарне дерево пошуку ...?
nchaud

1
Я подивився за допомогою рефлектора і виявив, що в ньому не використовується двійкове дерево пошуку.
Даніель Іммс

Я думаю, що сортований словник - це дерево AVL або Red-Blacktree (всі операції коштують O (logn). А SortedList - це бінарний пошук (це в гіршому випадку коштує o (n) час) l
Ghoster

105

Ось табличний вигляд, якщо це допомагає ...

З точки зору ефективності :

+------------------+---------+----------+--------+----------+----------+---------+
| 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краще підійде. Дивіться це питання для отримання докладніших відомостей про те, коли ними користуватися.

Більше ви можете прочитати тут , тут , тут , тут і тут .


Зауважте, що якщо ви хочете гарної продуктивності та порівняно низького обсягу використання пам'яті та індексованого пошуку, врахуйте BDictionary<Key,Value>в LoycCore замість SortedDictionary.
Qwertie

1
Так, подивіться в нижній частині цієї статті . Виявляється, BDictionaryяк правило, повільніше, за SortedDictionaryвинятком дуже великих розмірів, але це швидше, ніж SortedListякщо є понад 700 предметів. Використання пам’яті повинно бути лише трохи вище, ніж SortedList(значно нижче SortedDictionary), завдяки використанню масивів у листі дерева.
Qwertie

22

Я зламав відкритий рефлектор, щоб подивитися на це, оскільки, здається, є дещо плутанини 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): недійсний

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): недійсний

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

Перегляньте сторінку 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>)>).


9
Цитований текст помилковий (і був оновлений на MSDN): SortedList не є "двійковим деревом пошуку", це "масив пар ключів / значень".
Eldritch Conundrum

12

Це візуальне зображення того, як вистави порівнюються між собою.


Звідки ви взяли цю інформацію? З цієї схеми ми бачимо, що Діктикар є кращим будь-яким способом, тому немає ніяких причин для існування інших.
alex kostin

9

Досить сказано вже на цю тему, однак, щоб зробити це просто, ось мій погляд.

Відсортований словник слід використовувати, коли-

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

З іншого боку, відсортований список слід використовувати, коли:

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

Сподіваюся, це допомагає !!


1

Доступ до індексу (згаданий тут) - це практична відмінність. Якщо вам потрібно отримати доступ до наступника чи попередника, вам потрібен SortedList. SortedDictionary не може цього зробити, тому ви досить обмежені тим, як ви можете використовувати сортування (перший / foreach).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.