Чтобы понять, когда использовать SotedSet, SortedDictionary или SortedList, сначала рассмотрим, когда вообще нужны SortedX, а не обычный Dictionary.
Dicitonary даёт вставку за O(1), удаление за O(1), и взятие элемента по ключу, тоже за O(1). Что ещё нужно для счастья? Ну например вернуть ключи-значения отсортированными по ключу. Dictionary сам не умеет, поэтому во-первых придётся потратить дополнительную память, чтобы выполнить эту сортировку. И сама сортировка обойдётся в O(n*log(n)).
Так вот, SortedX сделают это за O(n) и почти без дополнительной памяти. Причём SortedList должен справится даже быстрее SortedDictionary(SortedSet), так как он основан на массиве, а с ними процессоры работают быстрее, чем с деревьями, на которых основан второй.
Но дело в том что за это преимущество вы возможно уже заплатили при вставке. Если вставлять не все элементы сразу в SortedX, а по одному, то суммарно вставки обойдутся:
- Dictionary
O(n)
- SortedDictionary
O(n*log(n))
- SortedList
O(n*n)
Отсюда вывод по выбору:
- вставки случаются часто, а сортированный перебор редко - Dictionary
- и вставки часто и сортированные переборы тоже - SortedDictionary
- вставки редко, а сортированные переборы часто - SortedList
Теперь что такое SortedDictionary<TKey, TValue>
. Это такая обёртка над SortedSet<KeyValuePair<TKey, TValue>>
, но многие возможности кастрированы. Благо, можно вернуть себе отрезанные возможности, достаточно просто использовать второй вместо первого и позаимствовать код KeyValuePairComparer из SortedDictionary. Суть компаратора проста - для сравнений используем дефолтный компаратор по типу ключа и сравниваем только ключи.
С чем ещё плохо справляется стандартный Dictionary? Он бесполезен при поиске по диапазону значений. Придётся сделать полный перебор O(n).
SortedDictinary тут бессилен только из-за интерфейса.
SortedList отлично подойдёт, если границы диапазона это ключи.
O(log(n)) на найти границы, и O(m) на перебрать диапазон, где m - число вхождений в диапазоне.
Если же границы, это не ключи, то можно уложиться в ту же сложность, но встроенных интерфейсов для этого нет.
SortedSet изначально имеет метод на получение подмножества по произвольному диапазону - GetViewBetween. SortedSet<KeyValuePair<TKey, TValue>> с компаратором тоже позволит пользоваться этой фичей. Сложность плюс-минус такая же, как у SortedList.
Ещё Dictionary не умеет выдавать максимальный-минимальны элемент без полного перебора O(n). SortedSet и SortedList смогут за O(1). SortedDictionary - мог бы, но спасибо разработчикам, они похоже хотели скрыть, что там дерево, и спрятали эти возможности так же.