繁体   English   中英

快速排序输出不一致

[英]Inconsistent output of quick sort

我想体验最坏的快速排序情况。 因此,我生成了一个降序数组。 使用快速排序进行排序后,有时数组的第一个元素会变成垃圾,有时会像预期的那样变为 0。 当第一个元素是垃圾时,所有元素的顺序都会向上滑动,第二个元素变为 0,第三个元素变为 1,等等。这是我的代码:

void generateDescendingArray(int *arr, int n) {

    for(int i = n - 1; i >= 0; i--) {
       arr[n-i-1] = i;
    }
}

void quickSort(int *A, int start, int end) {
    if(end > start) {
       int s = partition(A, start, end); //split position
       quickSort(A, start, s - 1); //sort before the split
       quickSort(A, s + 1, end); //sort after the split
    }
}
int partition(int *A, int start, int end) {

    int pivot = A[start];
    int i = start;
    int j = end + 1;

    do {
    
        do { i++;
        } while(pivot > A[i]);
    
        do { j--;
        } while(pivot < A[j]);
    
        swap(&A[i], &A[j]);
    
    } while(j > i);
    swap(&A[i], &A[j]); //undo last swap when i >= j
    swap(&A[start], &A[j]);

    return j;
}
int main() {
   int A[n];
   generateDescendingArray(A, n);
   quickSort(A, 0, n);
   
   return 0;
}

根据评论中的诊断,您需要:

  • 通过在partition()循环之前检查ij防止扫描空分区。
  • 使用正确的索引 - 0n-1调用quickSort()

实验表明do { … } while (j > i); 循环公式也很干净。

这些变化导致:

#include <stdio.h>

static inline void swap(int *a, int *b) { int t = *a; *a = *b; *b = t; }
static int partition(int *A, int start, int end);

static
void generateDescendingArray(int *arr, int n) {

    for(int i = n - 1; i >= 0; i--) {
       arr[n-i-1] = i;
    }
}

static
void quickSort(int *A, int start, int end) {
    if(end > start) {
       int s = partition(A, start, end); //split position
       quickSort(A, start, s - 1); //sort before the split
       quickSort(A, s + 1, end); //sort after the split
    }
}

static
int partition(int *A, int start, int end) {

    int pivot = A[start];
    int i = start;
    int j = end + 1;

    while (i < j)
    {

        do { i++;
        } while(pivot > A[i]);

        do { j--;
        } while(pivot < A[j]);

        swap(&A[i], &A[j]);

    }
    swap(&A[i], &A[j]); //undo last swap when i >= j
    swap(&A[start], &A[j]);

    return j;
}

enum { NUM_PER_LINE = 10 };

static void print_data(const char *tag, const int *A, int num)
{
    printf("%s (%d):\n", tag, num);
    const char *pad = "";
    int i;
    for (i = 0; i < num; i++)
    {
        printf("%s%d", pad, A[i]);
        pad = " ";
        if (i % NUM_PER_LINE == NUM_PER_LINE - 1)
        {
            putchar('\n');
            pad = "";
        }
    }
    if (i % NUM_PER_LINE != 0)
        putchar('\n');
}

int main(void) {
   for (int n = 1; n < 24; n++)
   {
       int A[n];
       generateDescendingArray(A, n);
       print_data("Unsorted", A, n);
       quickSort(A, 0, n-1);
       print_data("Sorted", A, n);
   }

   return 0;
}

代码产生正确的输出,AFAICS:

Unsorted (1):
0
Sorted (1):
0
Unsorted (2):
1 0
Sorted (2):
0 1
Unsorted (3):
2 1 0
Sorted (3):
0 1 2
Unsorted (4):
3 2 1 0
Sorted (4):
0 1 2 3
…
Unsorted (21):
20 19 18 17 16 15 14 13 12 11
10 9 8 7 6 5 4 3 2 1
0
Sorted (21):
0 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19
20
Unsorted (22):
21 20 19 18 17 16 15 14 13 12
11 10 9 8 7 6 5 4 3 2
1 0
Sorted (22):
0 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19
20 21
Unsorted (23):
22 21 20 19 18 17 16 15 14 13
12 11 10 9 8 7 6 5 4 3
2 1 0
Sorted (23):
0 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19
20 21 22

使用 Hoare 的分区方案:

int partition(int *A, int start, int end) {

   int i = start - 1;
   int j = end + 1;
   int pivot = start;

   while(1) {
      while (A[++i] < A[pivot]);
      while (A[--j] > A[pivot]);

      if (i >= j) {
        return j;
      }
      // swap A[i] and A[j]
  }

  return j;
}

void quickSort(int *A, int start, int end) {
    if(start < end) {
       int s = partition(A, start, end);
       quickSort(A, start, s);
       quickSort(A, s + 1, end);
    }
 }

int main() {
    ...  
    quickSort(A, 0, n - 1); // CHANGED to n - 1 because you already have + 1 in partition
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM