QuickSort方法仅使用单个向量作为C 中的输入参数
QuickSort method using only a single vector as input parameter in C++
我正在尝试在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::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);
}
我像这样修改了您的代码。我认为枢轴索引是最后一项。并添加了一些测试代码。它正常工作。我认为,如果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。您还需要通过i
和j
。为了拥有一个参数界面,您可以写
vector<double> QuickSort(vector<double> & vec1, int i = 0, int j = vec1.size() - 1 ) {
int size = vec1.size();
....
- 将输入参数作为右值引用传递?
- 是否可以在命令行中将输入参数传递给可执行文件
- 用户输入作为参数C++
- C++基于输入参数的动态代码生成
- 我想知道为什么"std::unique_ptr<int> foo(新 int)"是合法的,因为"std::<int>unique_ptr"要求输入参数类型应该是"int"?
- 如何使用输入参数作为文件的传递?
- 如何设置默认参数以防用户不输入另一个参数
- C++ 如何根据作为输入传递的参数调用一个构造函数或另一个构造函数?
- 在未显式传递参数时默认使用 lambda 的用户输入
- 在函数中使用运算符重载,在 c++ 中使用 const 类型输入参数
- 提供变量作为 MATLAB 系统命令的输入参数,以便C++可执行文件
- isPalindrome不显示输出,isPalindrome函数未使用字符串输入作为字符串参数进行测试
- 如何使输入文本文件成为构造函数参数?c++
- 函数的函数无法识别输入参数
- C++ Catch 是否有类似 NUnit 的测试用例的东西,具有多个参数/输入选项
- 具体参数输入
- 为什么在参数输入之前将计算放置在代码中时,计算不起作用
- C 函数通过指针通过参考与参数输入参数
- 将命令行参数输入文件传递给要分析的类
- 将命令作为参数输入到另一个应用程序