SortedListとSortedDictionaryの違いは何ですか?


261

a SortedList<TKey,TValue>とaの間に実際の実用的な違いはありますSortedDictionary<TKey,TValue>か?どちらか一方だけを使用するような状況はありますか?



13
よくわかりません。SortedListにSortedList<TKey,TValue>1つではなく2つの型パラメーターがあるのはなぜSortedList<T>ですか?なぜ実装しないのIList<T>ですか?
大佐パニック

3
@ColonelPanicは、機能的にはSortedListが線形コレクションではなくマップであるためです。名前に騙されてはいけません。辞書のように、キーを渡すと、値が返されます。辞書は順不同ですが、SortedListは自然な順序で並べられます。
nawfal 2015

回答:


294

はい-パフォーマンス特性は大きく異なります。おそらく、それらを呼び出す方が良いでしょうSortedListし、SortedTreeそのようなより密接な実装を反映しています。

さまざまな状況でのさまざまな操作のパフォーマンスの詳細については、それぞれのMSDNドキュメント(SortedListSortedDictionary)を参照してください。ここに(SortedDictionaryドキュメントからの)良い要約があります:

SortedDictionary<TKey, TValue>ジェネリッククラスは、辞書内の要素の数であるnはO(Nログ)検索とバイナリ検索ツリーです。この点で、SortedList<TKey, TValue>ジェネリッククラスに似てい ます。2つのクラスには同様のオブジェクトモデルがあり、両方にO(log n)取得があります。2つのクラスが異なるのは、メモリの使用と挿入および削除の速度です。

  • SortedList<TKey, TValue>はよりも少ないメモリを使用しますSortedDictionary<TKey, TValue>

  • SortedDictionary<TKey, TValue>は、並べ替えられていないデータの挿入および削除操作が高速です。O(n)の場合とは対照的に、O(log n) SortedList<TKey, TValue>

  • リストが並べ替えられたデータから一度に入力される場合SortedList<TKey, TValue>は、よりも高速です SortedDictionary<TKey, TValue>

SortedList実際には、ツリーを使用するのではなく、ソートされた配列を維持します。それでも、バイナリ検索を使用して要素を見つけます。)


ポインタをありがとうございました。私はRTFMにあまりにも怠惰だと思います... SOの素敵な人々に尋ねる方がはるかに簡単です...;)私はあなたに両方の回答に投票しました。ジョンは、最初にトリガーされたことに対して回答クレジットを取得します。:)
Shaul Behr

2
私はそれが二分探索木であるとは思わないので、SortedList定義を修正すべきだと思います...?
nchaud、2013

1
リフレクターを使用して見たところ、バイナリ検索ツリーを使用していないことがわかりました。
Daniel Imms 2013

Sorteddictionaryは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 2016

1
はい、この記事の下部をご覧ください。それは結局のところBDictionaryより通常遅くなりSortedDictionary、非常に大きなサイズを除いて、それはより速くよりSortedList700の項目やそこらであるかどうか。ツリーのリーフで配列を使用しているため、メモリ使用量はをわずかに上回るSortedList(を大幅に下回るSortedDictionary)必要があります。
Qwertie 2016年

22

について少し混乱があるように見えるので、これを確認するために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

MSDNページでSortedListを確認してください

備考セクションから:

SortedList<(Of <(TKey, TValue>)>)ジェネリッククラスが持つ二分探索木であるO(log n)検索、n辞書内の要素の数です。この点で、SortedDictionary<(Of <(TKey, TValue>)>)ジェネリッククラスに似ています。2つのクラスは同様のオブジェクトモデルを持ち、どちらもO(log n)検索を行います。2つのクラスが異なるのは、メモリの使用と挿入および削除の速度です。

  • 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、2012

12

これは、パフォーマンスの比較方法を視覚的に表したものです。


その情報はどこから入手しましたか?このスキームから、Dictinaryが何らかの形でより優れていることがわかります。したがって、他の人が存在する理由はありません。
アレックスコスティン

9

トピックについてはすでに十分に述べられていますが、簡単にするために、ここに私の見解を示します。

ソートされた辞書は次の場合に使用する必要があります-

  • 追加の挿入および削除操作が必要です。
  • 順不同のデータ。
  • キーアクセスで十分であり、インデックスアクセスは必要ありません。
  • メモリはボトルネックではありません。

反対に、並べ替えられたリストは次の場合に使用する必要があります。

  • より多くのルックアップと少ない挿入と削除操作が必要です。
  • データはすでにソートされています(すべてではないにしても、ほとんど)。
  • インデックスアクセスが必要です。
  • メモリはオーバーヘッドです。

お役に立てれば!!


1

インデックスアクセス(ここで説明)が実際の違いです。後続または先行にアクセスする必要がある場合は、SortedListが必要です。SortedDictionaryはそれを行うことができないため、ソートの使用方法(first / foreach)にはかなり制限があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.