我正在尝试用C ++编写QuickSort方法。我认为我的问题在于:
if( i <= j )
因为这不是比较矢量中的值而是我的索引。我试图使用括号operator []来访问该值,但代码消耗内存并且不会自行结束。
此外,我宁愿将其保留为单个方法,而不是将其拆分为分区方法和排序方法。
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;
}
请提出建议和意见。
答案 0 :(得分:1)
编写递归函数的第一条规则是定义没有什么可做的情况。您的代码不会执行此操作,并且假定它永远不会到达。大小&lt; = 1的向量是空的,并且在这样的向量上测试vec1[i] > vec1[i+1]
是未定义的行为。
编写递归函数的第二个规则是确保每次内部调用都减少问题大小。你的代码没有这样做,它将整个向量传递给它自己(两次,如果第一个将返回)。
向量不是由double
索引,而是由size_t
s(或带有符号转换的int
s)索引。
您通过引用接受vec1
,改变它,然后在回复中复制它。做一个,而不是两者。
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::range
或range 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);
}
答案 1 :(得分:0)
我建议使用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);
}
将始终QuickSort
与vec1
一起开始。您还需要传递i
和j
。为了有一个参数接口,你可以写
vector<double> QuickSort(vector<double> & vec1, int i = 0, int j = vec1.size() - 1 ) {
int size = vec1.size();
....
答案 2 :(得分:0)
我修改了你的代码。我决定将枢轴指数作为最后一项。并添加了一些测试代码。它运作正常。我认为如果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