C:尝试实现双枢轴快速排序但陷入无限循环

C: Trying to implement a dual-pivot quicksort but getting stuck in an infinite loop

在写这篇文章之前,我试图找到一个用 C 实现的算法示例,但在 google 上搜索了一段时间后找不到。尽管我可能对编程术语不够精通,无法正确搜索它。此代码基于有关该算法的论文(Java 中的示例)和我发现的 Java 中的另一个实现。

目前陷入死循环,但我找不到原因。部分原因可能是因为我试图将代码转换为 C 但出错了。

#include <stdio.h>

void printArray(int A[], int size) {
    printf("[ ");
    int i = 0;
    for (i = 0; i < size; i++) {
        printf("%d", A[i]);
        if (i < size - 1) printf(", ");
    }
    printf(" ]\n");
}

void quickSort(int A[], int left, int right) {
    if (right <= left ) return;

    int temp;

    if (A[right] < A[left]) {
        temp = A[right];
        A[right] = A[left];
        A[left] = temp;
    }

    int pLow = left + 1;
    int pHigh = right - 1;
    int i = left + 1;

    while (i <= pHigh) {
        if (A[i] < A[pLow]) {
            temp = A[i];
            A[i] = A[pLow];
            A[pLow] = temp;
            A[pLow++];
            i++;
        }
        else if (A[pHigh] < A[i]) {
            temp = A[i];
            A[i] = A[pHigh];
            A[pHigh] = temp;
            A[pHigh--];
        }
        else i++;
    }

    temp = A[left];
    A[left] = A[--pLow];
    A[pLow] = temp;
    temp = A[right];
    A[right] = A[++pHigh];
    A[pHigh] = temp;

    quickSort(A, left, pLow-1);
    if (A[pLow] < A[pHigh]) quickSort(A, pLow+1, pHigh-1);
    quickSort(A, pHigh+1, right);
}

int main() {
    int size = 10;
    int array[10] = {1, 0, 7, 9, 6, 2, 5, 8, 4, 3};

    printf("Before: ");
    printArray(array, size);

    quickSort(array, 0, size-1);

    printf("After: ");
    printArray(array, size);

}

这很可疑...

int pLow = left + 1;
int pHigh = right - 1;

... 当您刚刚麻烦确保 A[left] < A[right],但没有做任何测试或修复 A[left + 1]A[right - 1] 的相对顺序时。我认为您想从子数组的最末端选择枢轴:

int pLow = left;
int pHigh = right;

不过,更重要的是,您的递归没有终止条件。当 right <= left.

时,您的 quickSort() 函数应该在不执行任何操作(尤其是不递归)的情况下终止

更新:

虽然我自己不会像这样实现它,但以下是我能想到的将起始代码转换为工作类型的最小更改:

void quickSort(int A[], int left, int right) {
    int temp;

    if (right <= left) return;

    if (A[right] < A[left]) {
        temp = A[right];
        A[right] = A[left];
        A[left] = temp;
    }
    /* A[left] and A[right] are the left and right pivot values */

    int pLow = left + 1;
    int pHigh = right - 1;
    int i = left + 1;

    while (i <= pHigh) {
        if (A[i] < A[left]) {
            temp = A[i];
            A[i++] = A[pLow];
            A[pLow++] = temp;
        }
        else if (A[right] < A[i]) {
            temp = A[i];
            A[i] = A[pHigh];  /* i not incremented here */
            A[pHigh--] = temp;
        }
        else i++;
    }

    temp = A[left];
    A[left] = A[--pLow];
    A[pLow] = temp;
    temp = A[right];
    A[right] = A[++pHigh];
    A[pHigh] = temp;

    quickSort(A, left, pLow - 1);
    if (A[pLow] < A[pHigh]) quickSort(A, pLow + 1, pHigh - 1);
    quickSort(A, pHigh + 1, right);
}

请特别注意,只有当枢轴值在 A[left]A[right] 中保持到那时为止,循环结束后的两次交换才有意义。但是,这意味着内部循环中的比较必须与 those 值进行比较,而不是与 A[pLow]A[pHigh].

进行比较

我保留了 pLowpHigh 的原始初始化(尽管我之前的评论);因此,这些代表了低分区和高分区中 下一个可用 位置的索引。我还更改了一些增量和减量。