【问题标题】:quicksort not working correctly快速排序无法正常工作
【发布时间】:2015-11-15 01:35:09
【问题描述】:

我在我的代码中找不到问题。它运行,但无法正确排序数组。我认为最让我困惑的部分是如何在递归过程中传递未排序的子数组。

#include<iostream>
using namespace std;

void quickSort(int*, int, int);
int partition(int*, int, int);

int main(){
    int const size = 10;
    int a[size] = {37, 2, 6, 4, 89, 8, 10, 12, 68, 45};

    for(int i=0; i<size; i++){
        cout << a[i] << " ";
    }
    quickSort(a, 0, size-1);
    cout << endl;   
    for(int i=0; i<size; i++){
        cout << a[i] << " ";
    }

}

void quickSort(int *array, int start, int end){
    if(start<end){
        int piv = partition(array, start, end);
        quickSort(array, 0, piv-1);
        quickSort(array, piv+1, end-1);
    }
}

int partition(int *array, int start, int end){
    int piv = array[start];
    int i = start+1;
    int j = end;
    while(i<j){
        while(array[i]<piv and i<end) i++;
        while(array[j]>piv) j--;
        if(i<j){
            int temp = *(array+i);
            *(array+i) = *(array+j);
            *(array+j) = temp;
        }

    }
    int temp = *array;
    *array = *(array+j);
    *(array+j) = temp;
    return j;
}

输出是这样的:

    37 2 6 4 89 8 10 12 68 45
    4 6 8 10 12 37 68 89 2 45

【问题讨论】:

标签: c++ pointers pivot quicksort partition


【解决方案1】:

记住end包容性,所以你不应该递归end-1,而是end

您的partition() 函数有几个错误:

  • 在嵌套的 while 循环中,您应该检查 i&lt;j,而不是 i&lt;end
  • 在嵌套的 while 循环中,您应该首先检查 i&lt;j,然后再将元素与 piv 进行比较。
  • 在循环之后,您应该检查j 是否指向元素> piv。如果是这样,您需要在执行交换之前减少j。考虑:
37 2 6 4 12 8 10 89 68 45 j 89 2 6 4 12 8 10 37 68 45
  • 循环之后,您总是 与整个数组中的 first 元素交换。我确定您打算array[start]交换。

顺便说一句,*(array+j)array[j] 是一样的。

希望这会有所帮助。

【讨论】:

    【解决方案2】:

    我注意到的第一件事是:

        quickSort(array, 0, piv-1);
        quickSort(array, piv+1, end-1);
    

    应该是:

        quickSort(array, start, piv-1);  // start, not 0
        quickSort(array, piv+1, end);    // end, not end-1
    

    在那之后,我认为通过在代码的关键位置添加cout语句会更容易确定问题的根源。这是我尝试过的:

    void quickSort(int *array, int start, int end){
    
        if(start<end){
           cout << "Before sort: ";
           for(int i=start; i<=end; i++){
              cout << array[i] << " ";
           }
           cout << std::endl;
            int piv = partition(array, start, end);
            std::cout << "Pivot index: " << piv << ", Pivot element: " << array[piv] << std::endl;
            quickSort(array, start, piv-1);
            quickSort(array, piv+1, end);
        }
    
        cout << "After sort: ";
        for(int i=start; i<=end; i++){
           cout << array[i] << " ";
        }
        cout << std::endl;
    }
    

    有了这些,我得到了以下输出:

    37 2 6 4 89 8 10 12 68 45 
    Before sort: 37 2 6 4 89 8 10 12 68 45 
    Pivot index: 6, Pivot element: 37
    Before sort: 10 2 6 4 12 8 
    Pivot index: 4, Pivot element: 10
    Before sort: 8 2 6 4 
    Pivot index: 3, Pivot element: 8
    Before sort: 4 2 6 
    Pivot index: 1, Pivot element: 4
    After sort: 2 
    After sort: 6 
    After sort: 2 4 6 
    After sort: 
    After sort: 2 4 6 8 
    After sort: 12 
    After sort: 2 4 6 8 10 12 
    Before sort: 89 68 45 
    Pivot index: 9, Pivot element: 2
    Before sort: 89 68 
    Pivot index: 8, Pivot element: 45
    After sort: 89 
    After sort: 
    After sort: 89 45 
    After sort: 
    After sort: 89 45 2 
    After sort: 68 4 6 8 10 12 37 89 45 2 
    68 4 6 8 10 12 37 89 45 2 
    

    这让我在partition 中仔细观察,我注意到你有:

    int temp = *array;
    *array = *(array+j);
    *(array+j) = temp;
    

    这解释了为什么来自分区数组下半部分的数字被拉入分区数组的上半部分。它们应该是:

    int temp = *(array+start);
    *(array+start) = *(array+j);
    *(array+j) = temp;
    

    它对我来说更具可读性:

    int temp = array[start];
    array[start] = array[j];
    array[j] = temp;
    

    通过这些更改,数组排序出来了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-13
      • 1970-01-01
      • 1970-01-01
      • 2015-05-15
      • 2016-07-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多