2010-10-24

MergeSort and LINQ

Here is an implementation of the merge sort algorithm, which operates on a sequence/list of items:


using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;

namespace MergeSort
{
public static class MergeSort_Extensions
{
public static IEnumerable<T> MergeSort<T>(this IList<T> items, Comparison<T> comparison)
{
return MergeSortInternal<T>(items, items.Count, comparison);
}

public static IEnumerable<T> MergeSort<T>(this IEnumerable<T> items, Comparison<T> comparison)
{
return MergeSortInternal<T>(items, items.Count(), comparison);
}

private static IEnumerable<T> MergeSortInternal<T>(IEnumerable<T> items, int count, Comparison<T> comparison)
{
Debug.Assert(items != null);
Debug.Assert(comparison != null);

if (count == 0)
yield break;

if (count == 1)
{
yield return items.First();
yield break;
}

// sort both halves recursively
IEnumerator<T> enumA = MergeSortInternal<T>(items.Take<T>(count / 2), count / 2, comparison).GetEnumerator();
IEnumerator<T> enumB = MergeSortInternal<T>(items.Skip<T>(count / 2), count - count / 2, comparison).GetEnumerator();

bool movedA = enumA.MoveNext();
bool movedB = enumB.MoveNext();
Debug.Assert(movedA && movedB);

// merge
while (true)
{
if (comparison(enumA.Current, enumB.Current) > 0)
{
// swap enumerators
IEnumerator<T> iterTemp = enumA;
enumA = enumB;
enumB = iterTemp;
}

yield return enumA.Current;
if (enumA.MoveNext() == false)
{
// return the remaining items
do yield return enumB.Current;
while (enumB.MoveNext());
break;
}
}
}
}
}



P.S. The code was formatted with http://formatmysourcecode.blogspot.com/