c - 快速排序不适用于大输入

标签 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;
}

最佳答案

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

请注意,对于已经排序的数组,您的枢轴选择很差;你真的应该选择 3 个甚至 9 个值的中位数。

附言其他理想的优化:1)切换到小分区的插入排序——最佳截止点是机器相关的。另一种方法是不对小于一定大小的分区进行排序,然后在快速排序完成后对整个数组进行插入排序。如果仔细操作,也可以使用堆排序代替插入排序;谷歌介绍。 2) quicksort 做两次递归调用;通过设置 start = part + 1 和循环来消除第二个。 3) 通过先对较大的分区进行快速排序来避免堆栈溢出的可能性。 4) 通过使用显式堆栈消除第一次递归调用。 5) 内联 swap() 和 partition()。 6) 不要理会这些,只需调用 qsort 库例程即可。 :-)

关于c - 快速排序不适用于大输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4999899/

相关文章:

用 C 计算二维数组的标准差

c - 单个结构上的快速排序。不能正常工作

algorithm - 关于快速排序 killer

c - 使用 gcc wrap 选项时出现段错误

algorithm - 比较排序算法中 Ω(n logk) 最坏情况复杂度的证明

java - (java) 快速排序,先按数字对数字-字符对进行排序,然后按字符排序

c - c中的霍尔快速排序

c - 分段默认(核心转储)

c - 为什么 strcmp 的返回不同?

java - 不满意链接错误 : no libhello in java. library.path