Skip to content

Instantly share code, notes, and snippets.

@CallumWatkins
Last active February 4, 2019 16:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save CallumWatkins/02bd44a624a0d370650488ffb1042382 to your computer and use it in GitHub Desktop.
Save CallumWatkins/02bd44a624a0d370650488ffb1042382 to your computer and use it in GitHub Desktop.
Two binary search implementations using ReadOnlySpan<T>. One returns the index of the item, the other returns a Boolean. License: MIT
/// <summary>
/// Searches an entire one-dimensional sorted span for a value using the specified comparer.
/// </summary>
/// <typeparam name="T">The type of the items being searched.</typeparam>
/// <param name="span">The sorted span to search.</param>
/// <param name="item">The item to search for.</param>
/// <param name="comparer">The comparer implementation to use when comparing elements.</param>
/// <returns>True if the item is in the input; false otherwise.</returns>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="comparer"/> is null.</exception>
static bool BinarySearch<T>(ReadOnlySpan<T> span, T item, IComparer<T> comparer)
{
if (comparer == null) throw new ArgumentNullException(nameof(comparer));
while (span.Length > 0)
{
int i = span.Length / 2;
int comparison = comparer.Compare(item, span[i]);
if (comparison < 0) span = span.Slice(0, i);
else if (comparison > 0) span = span.Slice(i + 1);
else return true;
}
return false;
}
/// <summary>
/// Searches an entire one-dimensional sorted span for a value using the specified comparer.
/// </summary>
/// <typeparam name="T">The type of the items being searched.</typeparam>
/// <param name="span">The sorted span to search.</param>
/// <param name="item">The item to search for.</param>
/// <param name="comparer">The comparer implementation to use when comparing elements.</param>
/// <returns>The index of the item if found; -1 otherwise.</returns>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="comparer"/> is null.</exception>
static int BinarySearch<T>(ReadOnlySpan<T> span, T item, IComparer<T> comparer)
{
if (comparer == null) { throw new ArgumentNullException(nameof(comparer)); }
int position = 0;
while (span.Length > 0)
{
int i = span.Length / 2;
int comparison = comparer.Compare(item, span[i]);
if (comparison < 0) { span = span.Slice(0, i); }
else if (comparison > 0)
{
span = span.Slice(i + 1);
position += i + 1;
}
else { return position + i; }
}
return -1;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment