如何使快速排序递归?

Posted

技术标签:

【中文标题】如何使快速排序递归?【英文标题】:How to make quick sort recursive? 【发布时间】:2015-07-29 20:56:33 【问题描述】:

目前我正在尝试进行递归快速排序。快速排序有很多不同的方法,但对于我的方法,我必须取数组的第一个元素,并始终使用数组的第一个元素作为枢轴。然后我将它与所有元素进行比较并获得比较总数。小于数组的元素应该在枢轴后面,然后是更大的元素。所以应该是小于pivot的pivot|大于pivot的pivot。在比较所有枢轴之后,您应该取出小于枢轴的一侧的最后一个元素并将其与前面的枢轴交换。目前,我对如何使其递归感到迷茫,因为我相信我已经成功编写了第一遍代码。我被困在试图使其递归,以便它会调用自身的多次传递并且它们被拆分。再次对所有内容进行排序将是愚蠢的。相反,它应该将数组分成两部分,并通过小于原始枢轴的一侧和大于原始枢轴的一侧递归。这是一个测试用例,因为我后来不得不在一个包含 10,000 个数字的数据文件上使用这个算法(这就是我使用 long long 的原因,尽管现在我想起来,这可能是矫枉过正)。

下面是我的 C++ 代码:

    #include <stdio.h>
    #include <iostream>
    using namespace std;

    long long quicksort(long long arr[],long long leftbegin, long long rightend)
    
        long long i = leftbegin + 1;
        long long pivot = arr[leftbegin];
        long long comparisons = 0;
        for(long long j = i; j < 8; j++)
        
            if(arr[j] > pivot)
            
                rightend++;
                comparisons ++;
            
            if(arr[j] < pivot)
            
                long long temp = 0;
                temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
                comparisons ++;
                i = i+1;
            
        
        long long temp = 0;
        temp = arr[0];
        arr[0] = arr[i-1];
        arr[i-1] = temp;
    //    for(int x = 0; x< 8; x++)
    //    
    //        if(arr[x+1] >= arr[x])
    //        
    //    
    //        
    //        else
    //        
    //            quicksort(arr,0,i);
    //            quicksort(arr,i+1,(rightend + 0));
    //        
    //    
    //    
        return comparisons;
    

    /* Driver program to test above functions */
    int main ()
    
        long long arr[8]= 3,8,2,5,1,4,7,6;
        cout<<"the number of comparisons are "<<quicksort(arr,0,8)<<endl;
        cout<<endl<<"arr is "<<endl;
        for(int i = 0; i < 8; i++)
        
            cout<<arr[i]<<endl;
        

    

如果我删除了 cmets 并运行带有注释部分的代码,它会在 long long temp = 0; 时给我错误,它会说 exec bad access,即使它能够成功运行。如果重要的话,我会使用 mac 和 Xcode。

【问题讨论】:

好的,我会这样做的。 谢谢,希望我能尽快得到它。 嘿,10000 很容易放入 short int。您至少需要 10 位数字才能超过 long int 第一个for-loop 有一个硬编码的8,它应该是rightendrightend++ 没有意义。为什么数组会变大? comparison++ 放错了位置,即使 arr[j] == pivot) 你仍然进行了 2 次比较,但你说你做了 0。为什么你 swaping arr[0]arr[i-1]? bug太多了,答案和你的代码不会有太多共同点,所以你还不如去wikipedia之类的找个实现。 其实rightend不应该是rightend++,我已经在我的代码中改变了。交换的原因只是因为我必须这样做。这也是有道理的,否则如果枢轴始终是第一个元素,那么枢轴将如何排序。通过进行交换,我将第一个元素与小于它的最后一个元素交换。这将其从枢轴|小于枢轴|大于枢轴。 to小于pivot|pivot|大于pivot。 【参考方案1】:

这是一个使用递归的 QuickSort 的 C++ 实现:

#include <cstdio>
#include <algorithm>

using namespace std;
int partition (int arr[], int low, int high)

    int pivot = arr[high];    //taking the last element as pivot
    int i = (low - 1);
    for (int j = low; j <= high- 1; j++)
    
        // If current element is smaller than or
        // equal to pivot
        if (arr[j] <= pivot)
        
            i++;
            swap(arr[i], arr[j]);
        
    
    swap(arr[i + 1], arr[high]);
    return (i + 1);


void quickSort(int arr[], int low, int high)

    if (low < high)
    
        int pi = partition(arr, low, high);
        quickSort(arr, low, pi - 1);
        quickSort(arr, pi + 1, high);
    


int main()

    int arr[] = 10, 7, 8, 9, 1, 5;
    int n = sizeof(arr)/sizeof(arr[0]);
    quickSort(arr, 0, n-1);

    return 0;

【讨论】:

【参考方案2】:

这是一个使用 std::nth_element() 的简短版本:

template <class ITR> void quick_sort(ITR b, ITR e) 
    if(e-b < 2) 
        return;
    
    ITR m = b+(e-b)/2;
    std::nth_element(b, m, e);
    quick_sort(b,m);
    quick_sort(m,e);

它可以被任何随机访问迭代器调用,例如,

std::vector<int> V = ....;
quick_sort(V.begin(), V.end());

注意:它可能比标准快速排序更昂贵,但它很有趣,因为排序标准可以在级别之间更改。例如,此功能可用于沿空间填充曲线(希尔伯特排序)组织多维点数据,如 CGAL 库 [1] 中所做的那样。注意: std::nth_element() 在 gcc 4.8.1 [2] 中存在错误,但在更新的版本中已修复。

[1]http://doc.cgal.org/latest/Spatial_sorting/index.html

[2]https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58800

【讨论】:

以上是关于如何使快速排序递归?的主要内容,如果未能解决你的问题,请参考以下文章

PHP 快速排序

快速排序(三种算法实现和非递归实现)

c++ 快速排序

如何在我的递归快速排序算法中防止堆栈溢出

排序算法-快速排序

混合快速/合并排序对随机数据的性能