Написание двоичного поиска самостоятельно может быть трудным.
К счастью, Microsoft уже написала довольно надежный: Array.BinarySearch<T>
. Фактически это метод, который SortedList<TKey, TValue>.IndexOfKey
использует внутренне . Единственная проблема в том, что он принимает аргумент T[]
вместо любого IList<T>
(например, SortedList<TKey, TValue>.Keys
).
Вы знаете что, хотя? Есть этот замечательный инструмент под названием Reflector , который позволяет вам просматривать исходный код .NET ...
Проверьте это: универсальный BinarySearch
метод расширения для IList<T>
, взятый прямо из отраженного кода реализации Array.BinarySearch<T>
от Microsoft.
public static int BinarySearch<T>(this IList<T> list, int index, int length, T value, IComparer<T> comparer) {
if (list == null)
throw new ArgumentNullException("list");
else if (index < 0 || length < 0)
throw new ArgumentOutOfRangeException((index < 0) ? "index" : "length");
else if (list.Count - index < length)
throw new ArgumentException();
int lower = index;
int upper = (index + length) - 1;
while (lower <= upper) {
int adjustedIndex = lower + ((upper - lower) >> 1);
int comparison = comparer.Compare(list[adjustedIndex], value);
if (comparison == 0)
return adjustedIndex;
else if (comparison < 0)
lower = adjustedIndex + 1;
else
upper = adjustedIndex - 1;
}
return ~lower;
}
public static int BinarySearch<T>(this IList<T> list, T value, IComparer<T> comparer) {
return list.BinarySearch(0, list.Count, value, comparer);
}
public static int BinarySearch<T>(this IList<T> list, T value) where T : IComparable<T> {
return list.BinarySearch(value, Comparer<T>.Default);
}
Это позволит вам вызвать list.Keys.BinarySearch
и получить отрицательное побитовое дополнение нужного вам индекса в случае, если нужный ключ не найден (ниже взята в основном прямо из ответа Цамана):
int index = list.Keys.BinarySearch(i);
if (index < 0)
index = ~index;
var item = index < list.Count ? list[list.Keys[index]] : null;
return item;