快速排序算法 - 三种中位数

时间:2014-04-18 17:01:22

标签: c# algorithm quicksort

我有以下快速排序算法,它使用最左边的作为一个工作得很好的枢轴:

public static void QuickSortLeft(int[] array, int start, int end)
{
    int left = start;
    int right = end;

    int pivot = array[start];

    while (left <= right)
    {
        while (array[left] < pivot)
        {
            left++;
        }

        while (array[right] > pivot)
        {
            right--;
        }

        if (left <= right)
        {
            swap(array,left, right);

            left++;
            right--;
        }
    }

    // Recursive calls
    if (start < right)
    {
        QuickSortLeft(array, start, right);
    }

    if (left < end)
    {
        QuickSortLeft(array, left, end);
    }
}

现在我尝试对上面的三个中位数进行优化我取第一个,最后一个和中间位置的中位数并使用中位数作为下面的枢轴,但是我得到一个StackOverflow异常

public static void QuickSortMedian(int[] array, int start, int end)
{
    int left = start;
    int right = end;

    int pivot = (array[start] + array[(start + (end - start)) / 2] + array[end]) / 2;

    while (left <= right)
    {
        while (array[left] < pivot)
        {
            left++;
        }

        while (array[right] > pivot)
        {
            right--;
        }

        if (left <= right)
        {
            swap(array, left, right);

            left++;
            right--;
        }
    }

    // Recursive calls
    if (start < right)
    {
        QuickSortMedian(array, start, right);
    }

    if (left < end)
    {
        QuickSortMedian(array, left, end);
    }
}

2 个答案:

答案 0 :(得分:2)

您正在计算平均值(但不正确 - 应该是/3,而不是/2),而不是中位数。

你应该选择三者的中间元素。

类似于:(伪代码)

sort(left, mid, right)
pick mid

使用当前代码,它可能最终得到的值大于其他所有代码,因此您可能最终将0个元素向右分区,只是重复向左移动相同的数据。

答案 1 :(得分:-1)

这会给你中位数:

public static class Extensions
{
    public static T Median<T>(this IEnumerable<T> source) where T:IComparable<T>
    {
        if (source == null)
        {
            throw new ArgumentException("source");
        }
        var sortedValues = source.OrderBy(v => v).ToList();
        if (sortedValues.Count == 0)
        {
            throw new InvalidOperationException("Sequence contains no elements");
        }
        var midpoint = (sortedValues.Count/2);
        return sortedValues[midpoint];
    }
}