C# 这是快速排序吗?

C# 这是快速排序吗?,c#,algorithm,quicksort,in-place,C#,Algorithm,Quicksort,In Place,我正试图写一个快速排序,以供我自己启发。我用这本书作为指南。我的代码有效。它似乎应该在O(n logn)时间内运行。我试图对我的代码进行计时以检查复杂性(即,当我将输入大小增加一倍时,运行时间是否会增加大约n logn),但我仍然不确定 我的代码似乎很简单。我在适当的地方做这类工作。我看到的其他实现使用了分区函数,而我没有。这让我觉得我已经实现了一些其他的排序算法。这是一个快速排序算法吗 public static void QuickSortInPlace(int[] arr) { Q

我正试图写一个快速排序,以供我自己启发。我用这本书作为指南。我的代码有效。它似乎应该在O(n logn)时间内运行。我试图对我的代码进行计时以检查复杂性(即,当我将输入大小增加一倍时,运行时间是否会增加大约n logn),但我仍然不确定

我的代码似乎很简单。我在适当的地方做这类工作。我看到的其他实现使用了分区函数,而我没有。这让我觉得我已经实现了一些其他的排序算法。这是一个快速排序算法吗

public static void QuickSortInPlace(int[] arr)
{
    QuickSortInPlace(arr, 0, arr.Length - 1);
}

private static void QuickSortInPlace(int[] arr, int left, int right)
{
    if (left < right)
    {
        //move the middle int to the beginning and use it as the pivot
        Swap(arr, left, (left + right) / 2);

        int pivotIndex = left;
        int pivot = arr[pivotIndex];
        int min = left + 1;
        int max = right;

        for (int i = min; i <= max; i++)
        {
            if (arr[i] > pivot)
            {
                Swap(arr, i, max);
                max--; //no longer need to inspect ints that have been swapped to the end
                i--; //reset the loop counter to inspect the new int at the swapped position
            }
        }

        //move pivot to its sorted position
        Swap(arr, max, pivotIndex);

        //recurse on the sub-arrays to the left and right of the pivot
        QuickSortInPlace(arr, left, max - 1);
        QuickSortInPlace(arr, max + 1, right);
    }
}
publicstaticvoidquicksortinplace(int[]arr)
{
快速排序空间(arr,0,arr.Length-1);
}
私有静态void QuickSortInPlace(int[]arr,int left,int right)
{
if(左<右)
{
//将中间的int移到开头,并将其用作轴
交换(arr,左,(左+右)/2;
int pivotIndex=左;
int pivot=arr[pivotIndex];
int min=左+1;
int max=右;
对于(int i=min;i轴)
{
交换(arr、i、最大值);
max--;//不再需要检查已交换到末尾的整数
i--;//重置循环计数器以检查交换位置的新int
}
}
//将枢轴移动到其排序位置
交换(arr、max、数据透视索引);
//在轴的左侧和右侧的子数组上递归
快速排序空间(arr,左侧,最大值-1);
QuickSortInPlace(arr,最大+1,右侧);
}
}
第二个版本基于杜克林的回应

public static void QuickSortInPlace3(int[] arr, int min, int max)
{
    if (min < max)
    {
        int pivotIndex = min;
        int pivot = arr[pivotIndex];

        int left = min;
        int right = max;

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

            while (arr[right] > pivot)
                right--;

            if (left <= right)
            {
                Swap(arr, left, right);
                left++;
                right--;
            }
        }

        QuickSortInPlace3(arr, min, right);
        QuickSortInPlace3(arr, left, max);
    }
}
公共静态无效QuickSortInPlace3(int[]arr,int min,int max)
{
如果(最小值<最大值)
{
int pivotIndex=min;
int pivot=arr[pivotIndex];
int左=分钟;
int right=max;
while(左枢轴)
对--;

如果(left是的,那么它肯定非常接近于quicksort来分类,或者至少是一个次要的变体

您正在对数据进行分区,只是没有单独的函数

你确实发生了一些奇怪的事情

通常,使用quicksort的就地变量,当左索引小于轴时,增加左索引,当右索引大于轴时,减少右索引,然后交换两个索引(因为仅执行涉及两个元素的交换,这两个元素都位于错误的一侧)

但是,您只是增加了左边的值,因此您可以从右边交换已经较大的元素。这可能会导致交换次数超出必要数量,尽管渐进运行时间应该是相同的

下面是一些“正常”变体的伪代码:(取自)

离开时≤ 正确的
而数组[左]pivot
右:=右-1
如果留下≤ 正确的
将数组[左]与数组[右]交换
左:=左+1
右:=右-1

我无法理解您粘贴的伪代码。快速排序的循环不变量是,在迭代之后,轴位于正确的位置。使用我上面粘贴的第二个版本,我发现这不是真的(即使代码可以工作)。下面是一个示例运行:输入{
3
,2,4,1,5}->first swap{1,2,
4
,3,5}->第二次交换{1,2,3,4,5}。我在每一步都突出显示了枢轴。在第一次交换之后,第一个枢轴
3
不在其最终位置。这违反了循环不变量,但在第二次交换之后,数组是有序的。你知道为什么吗?枢轴元素在哪里并不重要。如果它在左侧,它将是其中最大的元素子数组,放在最右边的位置。如果它在右边,它将是最小的,被放置在最左边的位置。所以,无论哪种方式,它都在中间。虽然把它放在中间,但会导致较少的比较,因为你永远不会再将它与任何事物进行比较。
while left ≤ right
    while array[left] < pivot
        left := left + 1
    while array[right] > pivot
        right := right - 1
    if left ≤ right
        swap array[left] with array[right]
        left := left + 1
        right := right - 1