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

时间:2015-03-30 18:26:57

标签: c infinite-loop quicksort

在写这篇文章之前,我试图找到一个用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);

}

1 个答案:

答案 0 :(得分:0)

这很可疑......

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

...当您遇到麻烦时确保A[left] < A[right],但没有做任何事情来测试或修正A[left + 1]A[right - 1]的相对顺序。我想你想从子阵列的最末端选择枢轴:

int pLow = left;
int pHigh = right;

但更重要的是,您的递归没有终止条件。 quickSort()时,right <= left函数应该终止而不做任何事情(特别是没有递归)。

<强>更新

虽然我不会像我自己那样实现它,但以下代表了我可以想出的将起始代码转换为工作类的最小变化:

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]之前维持枢轴值时,循环结束后的两次交换才有意义。但是,这意味着内循环中的比较必须与那些值相对应,而不是A[pLow]A[pHigh]

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