web-dev-qa-db-ja.com

SortedList <>、SortedDictionary <>、Dictionary <>

それみつけたよ SortedList<TKey, TValue>SortedDictionary<TKey, TValue>およびDictionary<TKey, TValue>同じインターフェースを実装します。

  1. いつSortedListSortedDictionaryDictionaryで選ぶべきですか?
  2. アプリケーションの面でSortedListSortedDictionaryの違いは何ですか?
84
Sunder
  1. 2つのいずれかの要素を反復処理すると、要素が並べ替えられます。 Dictionary<T,V>ではそうではありません。

  2. [〜#〜] msdn [〜#〜]SortedList<T,V>SortedDictionary<T,V>の違いに対処します。

SortedDictionary(TKey、TValue)ジェネリッククラスは、 バイナリ検索ツリー O(log n)検索で、nはディクショナリの要素数です。この点で、SortedList(TKey、TValue)ジェネリッククラスに似ています。 2つのクラスには類似したオブジェクトモデルがあり、両方ともO(log n)取得があります。 2つのクラスの違いは、メモリの使用と挿入および削除の速度です。

SortedList(TKey、TValue)は、SortedDictionary(TKey、TValue)よりも少ないメモリを使用します。

SortedDictionary(TKey、TValue)には、ソートされていないデータの挿入と削除の操作が高速です。O(log n)は、O(n) SortedList(TKey、TValue)に対して)。

ソートされたデータからリストが一度に作成される場合、SortedList(TKey、TValue)はSortedDictionary(TKey、TValue)よりも高速です。

91
Szymon Rozga

enter image description here

辞書の違いに言及します。

上の写真は、Dictionary<K,V>は、すべての場合でSorted analogよりも同等または高速ですが、要素の順序が必要な場合、たとえばそれらを印刷するには、Sorted oneが選択されます。

Src: http://people.cs.aau.dk/~normark/oop-csharp/html/notes/collections-note-time-complexity-dictionaries.html

59
Lev

パフォーマンステスト-SortedList vs.SortedDictionary vs.Dictionary vs.Hashtable の結果を要約すると、さまざまなシナリオでの最高から最低までの結果:

メモリ使用量:

SortedList<T,T>
Hashtable
SortedDictionary<T,T>
Dictionary<T,T>

挿入:

Dictionary<T,T>
Hashtable
SortedDictionary<T,T>
SortedList<T,T>

検索操作:

Hashtable
Dictionary<T,T>
SortedList<T,T>
SortedDictionary<T,T>

foreachループ操作

SortedList<T,T>
Dictionary<T,T>
Hashtable
SortedDictionary<T,T>
20
NullReference
  1. コレクションを反復処理するときにキーでコレクションをソートする場合。データを並べ替える必要がない場合は、ディクショナリのみを使用するほうが適切です。パフォーマンスが向上します。

  2. SortedListとSortedDictionaryはほぼ同じことを行いますが、実装方法が異なるため、長所と短所が異なります ここで説明

9
Meta-Knight

提案された回答はパフォーマンスに焦点を合わせていることがわかります。以下の記事では、パフォーマンスに関する新しい情報は提供していませんが、基礎となるメカニズムについて説明しています。また、質問で言及されている3つのCollection型には焦点を当てていないが、_System.Collections.Generic_名前空間のすべての型を扱っていることに注意してください。

http://geekswithblogs.net/BlackRabbitCoder/archive/2011/06/16/c.net-fundamentals-choosing-the-right-collection-class.aspx

抽出物:

辞書<>

辞書はおそらく最も使用されている連想コンテナクラスです。辞書は、カバーの下でハッシュテーブルを使用するため、連想検索/挿入/削除の最速クラスです。キーがハッシュされるため、キータイプはGetHashCode()およびEquals()を適切に実装するか、構築時に辞書に外部IEqualityComparerを提供する必要があります。 。辞書内のアイテムの挿入/削除/ルックアップ時間は償却された一定時間です-O(1)-これは、辞書がどれだけ大きくなっても、何かを見つけるのにかかる時間は比較的残っていることを意味しますこれは高速ルックアップに非常に望ましいです唯一の欠点は、ハッシュテーブルを使用するという性質上、辞書が順序付けられていないことです。 ディクショナリのアイテムを順番に簡単にたどることはできません

SortedDictionary <>

SortedDictionaryは、Dictionaryと使用方法が似ていますが、実装が大きく異なります。 SortedDictionaryは、カバーの下のバイナリツリーを使用して、キーの順にアイテムを維持します。ソートの結果として、キーに使用される型は、キーを正しくソートできるようにIComparableを正しく実装する必要があります。ソートされたディクショナリは、アイテムの順序を維持するためにルックアップ時間を少し引き換えます。したがって、ソートされたディクショナリの挿入/削除/ルックアップ時間は対数-O(log n)です。一般的に、対数時間を使用すると、コレクションのサイズを2倍にすることができ、アイテムを見つけるために余分な比較を1回実行するだけで済みます。迅速な検索が必要であるが、キーの順にコレクションを維持できるようにする場合は、SortedDictionaryを使用します。

SortedList <>

SortedListは、汎用コンテナ内の他のソートされた連想コンテナクラスです。もう一度、SortedDictionaryと同様に、SortedListはキーを使用してキーと値のペアをソートします。ただし、SortedDictionaryとは異なり、SortedList内のitemsは、itemsのソート済み配列として格納されます。これは、挿入と削除が線形であることを意味します-O(n)-アイテムを削除または追加すると、リスト内のすべてのアイテムが上下に移動する場合があるためです。ただし、検索時間はO(log n )SortedListはバイナリ検索を使用して、キーでリスト内の項目を見つけることができるため、なぜこれを行う必要があるのでしょうか?さて、答えは、SortedListを前もって読み込む場合、挿入遅くなりますが、配列のインデックス作成はオブジェクトリンクをたどるよりも速いため、ルックアップはSortedDictionaryよりもわずかに速くなります。挿入と削除はまれです。


基礎となる手順の暫定的な要約

フィードバックはすべて歓迎していなかったと確信しているので大歓迎です。

  • すべての配列のサイズはnです。
  • ソートされていない配列= .Add/.RemoveはO(1)ですが、.Item(i)はO(n)です。
  • ソートされた配列= .Add/.RemoveはO(n)ですが、.Item(i)はO(1)です。

辞書

メモリ

KeyArray(n) -> non-sorted array<pointer>
ItemArray(n) -> non-sorted array<pointer>
HashArray(n) -> sorted array<hashvalue>

追加

  1. HashArray(n) = Key.GetHash#O(1)を追加
  2. KeyArray(n) = PointerToKey#O(1)を追加
  3. ItemArray(n) = PointerToItem#O(1)を追加

削除

  1. _For i = 0 to n_、iを見つけるHashArray(i) = Key.GetHash#O(log n)(ソートされた配列)
  2. 削除HashArray(i)#O(n)(ソートされた配列)
  3. KeyArray(i)#O(1)を削除
  4. ItemArray(i)#O(1)を削除

アイテムを取得

  1. _For i = 0 to n_、iを見つけるHashArray(i) = Key.GetHash#O(log n)(ソートされた配列)
  2. ItemArray(i)を返します

ループスルー

  1. _For i = 0 to n_、ItemArray(i)を返す

SortedDictionary

メモリ

KeyArray(n) = non-sorted array<pointer>
ItemArray(n) = non-sorted array<pointer>
OrderArray(n) = sorted array<pointer>

追加

  1. KeyArray(n) = PointerToKey#O(1)を追加
  2. ItemArray(n) = PointerToItem#O(1)を追加
  3. _For i = 0 to n_、iを見つけます。ここで、KeyArray(i-1) < Key < KeyArray(i)ICompareを使用)#O(n)
  4. OrderArray(i) = nを追加#O(n)(ソートされた配列)

削除

  1. _For i = 0 to n_、iを見つけるKeyArray(i).GetHash = Key.GetHash#O(n)
  2. KeyArray(SortArray(i))#O(1)を削除
  3. ItemArray(SortArray(i))#O(1)を削除
  4. 削除OrderArray(i)#O(n)(ソートされた配列)

アイテムを取得

  1. _For i = 0 to n_、iを見つけるKeyArray(i).GetHash = Key.GetHash#O(n)
  2. ItemArray(i)を返します

ループスルー

  1. _For i = 0 to n_、ItemArray(OrderArray(i))を返す

SortedList

メモリ

KeyArray(n) = sorted array<pointer>
ItemArray(n) = sorted array<pointer>

追加

  1. _For i = 0 to n_、iを見つけます。ここでKeyArray(i-1) < Key < KeyArray(i)ICompareを使用)#O(log n)
  2. KeyArray(i) = PointerToKey#O(n)を追加
  3. ItemArray(i) = PointerToItem#O(n)を追加

削除

  1. _For i = 0 to n_、iを見つけるKeyArray(i).GetHash = Key.GetHash#O(log n)
  2. KeyArray(i)#O(n)を削除
  3. ItemArray(i)#O(n)を削除

アイテムを取得

  1. _For i = 0 to n_、iを見つけるKeyArray(i).GetHash = Key.GetHash#O(log n)
  2. ItemArray(i)を返します

ループスルー

  1. _For i = 0 to n_、ItemArray(i)を返す
5
Ama

@ -Levが提示する各ケースにパフォーマンススコアを割り当てようとして、次の値を使用しました。

  • O(1)= 3
  • O(log n)= 2
  • O(n)= 1
  • O(1)またはO(n) = 2
  • O(log n)またはO(n) = 1.5

結果は次のとおりです(高い=良い):

Dictionary:       12.0 
SortedDictionary:  9.0 
SortedList:        6.5

もちろん、すべてのユースケースは特定の操作により大きな重みを与えます。

0
Jaime