QuickSort方法仅使用单个向量作为C 中的输入参数

QuickSort method using only a single vector as input parameter in C++

本文关键字:参数 输入 向量 方法 单个 QuickSort      更新时间:2023-10-16

我正在尝试在C 中编写QuickSort方法。我认为我的问题是:

if( i <= j )

因为这不是比较向量中的值,而是我的索引。我试图使用括号运算符[]访问该值,但是代码会消耗内存,并且不会自行结束。

我也希望将其保留为一种方法,而不是将其拆分为分区方法和分类方法。

std :: Sort与其他类型的方法一起实现。我只是在写这本书时遇到了麻烦。我的输入仅限于向量。

这就是我拥有的

vector<double> QuickSort(vector<double> & vec1){
    double i = 0;
    double j = vec1.size()-1;
    int size = vec1.size();
    double tmp;
    double pivot = vec1[(i + j) / 2];
//   partition 
    while (i <= j) {
        while (vec1[i] < pivot)
            i++;
        while (vec1[j] > pivot)
            j--;
        if (vec1[j] <= vec1[j-1]) {
            tmp = vec1[j-1];
            vec1[j-1] = vec1[j];
            vec1[j] = tmp;
            i++;
            j--;
        }
    }
//    recursion 
    if (vec1[i] > vec1[i+1]) {
        QuickSort(vec1);
    }
    if (vec1[j] <vec1[j-1]) {
        QuickSort(vec1);
    }
    return vec1;
}

请提出建议和建议。

编写递归功能的第一个规则是定义没有什么可做的情况。您的代码不执行此操作,并且假设从未达到它。具有大小&lt; = 1的向量是空置分类的,并且在这种向量上测试vec1[i] > vec1[i+1]是不确定的行为。

编写递归功能的第二个规则是确保您通过每个内部调用来减少问题大小。您的代码不执行此操作,它将整个向量传递给本身(两次,如果第一个将返回(。

向量不是由double s索引,而是由size_t s(或带有符号转换的int s(。

您是通过引用接受vec1,将其突变,然后在返回中复制它。do 一个,而不是两者。

从这里实现

namespace detail {    
    template<class FwdIt, class Compare = std::less<>>
    void QuickSortImpl(FwdIt first, FwdIt last, Compare cmp = Compare{})
    {
        auto const N = std::distance(first, last);
        if (N <= 1) return;
        auto const pivot = *std::next(first, N / 2);
        auto const middle1 = std::partition(first, last, [=](auto const& elem){ 
            return cmp(elem, pivot); 
        });
        auto const middle2 = std::partition(middle1, last, [=](auto const& elem){ 
            return !cmp(pivot, elem);
        });
        QuickSortImpl(first, middle1, cmp);
        QuickSortImpl(middle2, last, cmp);
    }   
}
void QuickSort(vector<double>& vec1)
{
    detail::QuickSortImpl(vec1.begin(), vec1.end());
}

如果您真的坚持使用一个函数参数,则可以使用范围库(boost::rangerange v3(

来完成。
template<class Range>
void QuickSort(Range& range)
{
    auto const N = std::distance(range.begin(), range.end());
    if (N <= 1) return;
    auto const pivot = *std::next(range.begin(), N / 2);
    auto left_range = boost::partition<boost::return_begin_found>(
        range.begin(), 
        range.end(), 
        [=](auto const& elem){ 
            return elem < pivot; 
        }
    );
    auto right_range = boost::partition<boost::return_found_end>(
        left_range.end(), 
        range.end(), 
        [=](auto const& elem){ 
            return !(pivot < elem);
        }
    );
    QuickSort(left_range);
    QuickSort(right_range);
}   

我像这样修改了您的代码。我认为枢轴索引是最后一项。并添加了一些测试代码。它正常工作。我认为,如果QuickSort函数从到索引参数可以实现。

可以更简单地实现。
#include <iostream>
#include <vector>
#include <chrono>

using namespace std ;
void printvector(vector<double> v) {
cout << "vector : " ;
for (double n : v) {
cout << n << " " ;
}
cout << endl ;
}
vector<double> QuickSort(vector<double>& vec1){
    double i = 0;
    double j = vec1.size()-2;
    double tmp;
    int pivotindex = vec1.size()-1 ;
    double pivot = vec1[pivotindex];
    if ( vec1.size()<=1 )
        return vec1 ;
    cout << "QuickSort: ";
    printvector(vec1) ;
    while (i <= j) {
        while (vec1[i] < pivot) {
            i++;
        }
        while (vec1[j] > pivot)
            j--;
         if (i <= j) {
            tmp = vec1[i];
            vec1[i] = vec1[j];
            vec1[j] = tmp;
            i++;
            j--;
        }
    }
    // pivot change
    vec1[pivotindex] = vec1[i] ;
    vec1[i]=pivot ;
    pivotindex=i ;
    cout << "pivotting: ";
    printvector(vec1) ;
    if (vec1.size()<=2 )
        return vec1 ;
    // partition
    vector<double> left_vec, right_vec ;
    vector<double>::iterator pivotiter = vec1.begin()+pivotindex ;
    copy(vec1.begin(), pivotiter, back_inserter(left_vec)) ;
    copy(pivotiter+1, vec1.end(), back_inserter(right_vec)) ;
    cout << "left: ";
    printvector(left_vec) ;
    cout << "right: ";
    printvector(right_vec) ;
   if (left_vec.size()>0 ) {
        QuickSort(left_vec);
        copy(left_vec.begin(), left_vec.end(), vec1.begin()) ;
    }
   if (right_vec.size()>0 ) {
        QuickSort(right_vec);
        copy(right_vec.begin(), right_vec.end(), pivotiter+1) ;
    }
    return vec1;
}
int main()
{
//vector<double> v { 5 } ;
//vector<double> v { 5, 3 } ;
//vector<double> v { 5, 3, 1 } ;
//vector<double> v { 1, 3, 5 } ;
//vector<double> v { 9,4,8,5,1,2,7 } ;
vector<double> v  ;
//srand( time(NULL) ) ;
int64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
srand( now ) ;
for (int i=0; i<rand()%30+1; i++) {
    v.push_back( rand()%10000 ) ;
}
cout << "input values: " ;
printvector(v) ;
vector<double> ret = QuickSort(v) ;
cout << "output values: " ;
printvector(ret) ;
cout << endl << endl ;
return 0 ;
}

输出就是这样。

input values: vector : 1778 9400 9330 783 3148 2029 9685 
QuickSort: vector : 1778 9400 9330 783 3148 2029 9685 
pivotting: vector : 1778 9400 9330 783 3148 2029 9685 
left: vector : 1778 9400 9330 783 3148 2029 
right: vector : 
QuickSort: vector : 1778 9400 9330 783 3148 2029 
pivotting: vector : 1778 783 2029 9400 3148 9330 
left: vector : 1778 783 
right: vector : 9400 3148 9330 
QuickSort: vector : 1778 783 
pivotting: vector : 783 1778 
QuickSort: vector : 9400 3148 9330 
pivotting: vector : 3148 9330 9400 
left: vector : 3148 
right: vector : 9400 
output values: vector : 783 1778 2029 3148 9330 9400 9685 

我建议使用std::sort,除非您有很好的理由不这样做。

为了使一个功能仅采用一个参数,std::sort的包装器可能看起来像这样,但是您正在复制向量。如果您不喜欢这个,则可以通过参考将其传递。

#include <iostream>   // std::cout
#include <algorithm>  // std::sort
#include <vector>     // std::vector
std::vector<double> mySort(const std::vector<double> unsorted) {
    std::vector<double> sorted = unsorted; 
    std::sort(sorted.begin(), sorted.end()); 
    return sorted;
}
int main() {
    std::vector<double> myvector{32, 71, 12, 45, 26, 80, 53, 33};
    for (const auto item : myvector) {
        std::cout << item << " ";
    }
    std::cout << std::endl;
    auto myvector_sorted = mySort(myvector);
    for (const auto item : myvector_sorted) {
        std::cout << item << " ";
    }
    std::cout << std::endl;
    return 0;
}

尽管如此,实施的底部并不有意义,因为

if (vec1[i] > vec1[i + 1]) {
    QuickSort(vec1);
}
if (vec1[j] < vec1[j - 1]) {
    QuickSort(vec1);
}

将始终使用vec1启动CC_11。您还需要通过ij。为了拥有一个参数界面,您可以写

vector<double> QuickSort(vector<double> & vec1, int i = 0, int j = vec1.size() - 1 ) {
    int size = vec1.size();
    ....