QuickSort不适用于大输入

时间:2011-02-15 04:34:47

标签: c quicksort

任何人都可以通过下面的快速排序实现发现问题吗?它似乎在具有10个以上元素的数组上失败。

void swap(int *p1, int *p2)
{
    int temp = *p1;
    *p1 = *p2;
    *p2 = temp;
}

void generateRandom(int arr[], int size)
{
    srand(time(NULL));
    int i;

    for (i = 0; i < size; i++)
    {
        arr[i] = rand() % 100;
    }
}

int partition(int arr[], int start, int end)
{
    int i = start, j = end;
    int pivot = arr[start];

    for (;;)
    {
        for (; arr[i] < pivot; i++);
        for (; arr[j] > pivot; j--);

        if (i < j)
        {
            swap(&arr[i], &arr[j]);
        }
        else
        {
            return j;
        }
    }
}

void quickSort(int arr[], int start, int end)
{
    int part;

    if (start < end)
    {
        part = partition(arr, start, end);
        quickSort(arr, start, part);
        quickSort(arr, part + 1, end);
    }
}

int main()
{
    generateRandom(arr, 100);
    for (i = 0; i < 100; i++)
    {
        printf("%d ", arr[i]);
    }
    printf("\n\n");

    quickSort(arr, 0, 99);
    for (i = 0; i < 100; i++)
    {
        printf("%d ", arr[i]);
    }
    printf("\n\n");

    return 0;
}

2 个答案:

答案 0 :(得分:2)

首先,您的代码无法编译。当我进行更正以使其编译时(在main中添加stdio.h和arr和i的定义),它会无限循环,如果分区以枢轴开始和结束,它将执行此操作。您需要在比较之前而不是之后递增和递减。您可以通过从i = start-1和j = end + 1开始并将内部循环更改为先增加或减少来实现,或者您可以将它们保留为原样并在交换后执行i ++和j--我做到了,排序有效。

请注意,对于已排序的数组,您的数据透视选择较差;你真的应该选择3或甚至9值的中位数。

P.S。其他理想的优化:1)切换到小分区的插入排序 - 最佳截止点取决于机器。另一种方法是不对低于特定大小的分区进行排序,然后在快速排序完成后对整个阵列执行插入排序。如果仔细进行,也可以使用heapsort而不是插入排序; google introsort。 2)quicksort做两个递归调用;通过设置start = part + 1和循环来消除第二个。 3)首先快速分配较大的分区,避免堆栈溢出的可能性。 4)通过使用显式堆栈消除第一次递归调用。 5)内联swap()和分区()。 6)不要打扰其中任何一个,只需调用qsort库例程。 : - )

答案 1 :(得分:0)

我有同样的问题, 但是我将while循环更改为do..while并且它有效。

这是我现在的新代码。

int partition(int a[], int lo, int hi)  {
int v = a[lo], i = lo, j = hi;

do  {

    do  {
        i++;
    } while(a[i] < v) ;

    do  {
        j--;
    }while(a[j] > v) ;

    if(i < j)   interchange(&a[i], &a[j]);  

}while(i < j);

interchange(&a[lo], &a[j]);     
return j;
}