C++ 快速排序3路分区太慢
我使用的是quicksort 3-way分区,但当向量大小大于10000时,速度太慢了。 我做错了什么?请引导我!任何帮助都将不胜感激 答案应在2.2秒内计算出来C++ 快速排序3路分区太慢,c++,vector,time,quicksort,C++,Vector,Time,Quicksort,我使用的是quicksort 3-way分区,但当向量大小大于10000时,速度太慢了。 我做错了什么?请引导我!任何帮助都将不胜感激 答案应在2.2秒内计算出来 #include <iostream> #include <vector> #include <cstdlib> #include <algorithm> using std::vector; using std::swap; void print(vector<int>
#include <iostream>
#include <vector>
#include <cstdlib>
#include <algorithm>
using std::vector;
using std::swap;
void print(vector<int> v)
{
for(int i = 0; i < v.size(); i++) std::cout << v[i] << " ";
std::cout << std::endl;
}
void partition2(vector<int> &a, int l, int r, int &i, int &j) {
int k;
int middle=(l+r)/2;
/*Selecting pivot as median of low, high and middle*/
if(((a[l]<=a[middle]) && (a[middle]<=a[r])) || ((a[r]<=a[middle]) && (a[middle]<=a[l])))
k=middle;
else if(((a[middle]<=a[l]) && (a[l]<=a[r])) || ((a[r]<=a[l]) && (a[l]<=a[middle])))
k=l;
else if(((a[middle]<=a[r]) && (a[r]<=a[l])) || ((a[l]<=a[r]) && (a[r]<=a[middle])))
k=r;
swap(a[l], a[k]);
//print(a);
int low_value = a[l];
int index_low = l;
int index_high = l;
int counter=l;
for (int i = l + 1; i <= r; i++) {
if (a[i] < low_value) {
swap(a[i], a[index_low]);
counter++;
low_value=a[l];
}
else if(a[i]==low_value)
{
index_high++;
swap(a[i], a[index_high]);
}
//print(a);
}
i=counter;
j=index_high;
//swap(a[l], a[j]);
//return j;
}
void randomized_quick_sort(vector<int> &a, int l, int r) {
if (l >= r) {
return;
}
int i,j;
partition2(a, l, r, i, j);
randomized_quick_sort(a, l, i-1);
randomized_quick_sort(a, j+1, r);
}
int main() {
int n;
std::cin >> n;
//while(1){
//n=100+rand()%99999;
//std::cout<<n<<std::endl;
vector<int> a(n);
for (size_t i = 0; i < a.size(); ++i) {
std::cin >> a[i];
//a[i]=1+rand()%99999999;
}
randomized_quick_sort(a, 0, a.size() - 1);
for (size_t i = 0; i < a.size(); ++i) {
std::cout << a[i] << ' ';
}
//std::cout<<"Pass\n";
//}
return 0;
}
#包括
#包括
#包括
#包括
使用std::vector;
使用std::swap;
无效打印(矢量v)
{
对于(int i=0;i
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <vector>
#include <ctime>
#include <random>
#include <chrono>
#include <iomanip>
using namespace std;
using namespace std::chrono;
//======= quick_sort =======//
template<typename T>
int partition(vector<T>& numbers, const int& left, const int& right)
{
swap(numbers[left], numbers[left + (right - left) / 2]);
T mid = numbers[left];
int i(left + 1), j(right);
while (i <= j)
{
while ( i <= j && numbers[i] <= mid ) i++;
while ( i <= j && numbers[j] > mid ) j--;
if ( i < j ) swap(numbers[i], numbers[j]);
}
swap(numbers[i - 1], numbers[left]);
return i - 1;
}
template<typename T>
void quick_sort_rec(vector<T>& numbers, const int& left, const int& right)
{
if (left >= right) return;
int p = partition(numbers, left, right);
quick_sort_rec(numbers, left , p - 1);
quick_sort_rec(numbers, p + 1 , right);
}
//=========================//
template<typename T>
T random_T(long min, long max)
{
return (T)min + static_cast<T>(rand()) / (static_cast<T>(RAND_MAX / ((T)(max - min))));
}
template<typename T>
float time_func(void (*f)(vector<T>&, const int&, const int&), vector<T>& a)
{
high_resolution_clock::time_point t1 = high_resolution_clock::now();
f(a, 0, a.size() - 1);
high_resolution_clock::time_point t2 = high_resolution_clock::now();
return 1000.0 * (duration_cast<microseconds>(t2 - t1).count()) / (float)(CLOCKS_PER_SEC); /// CLOCKS_PER_SEC;
}
int main()
{
srand((unsigned)(777));
vector<int> a;
for (int i = 0; i < 10000; i++)
{
a.push_back(random_T<int>(0, 1000));
}
cout << setprecision(10) << "quick sort rec = " << time_func(quick_sort_rec, a) << endl;
return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
使用名称空间std::chrono;
//=======快速排序=======//
模板
整数分区(向量和数字、常量整数和左、常量整数和右)
{
交换(数字[左]、数字[左+(右-左)/2]);
T mid=数字[左];
int i(左+1),j(右);
而(i我运行以下代码来测试partition2
int main(){
vector<int> a = {2, 1, 1, 9, 5, 3, 4, 2, 7};
int i, j;
partition2(a, 0, a.size() - 1, i, j);
for (auto i : a)
cout << i << ' ';
cout << '\n';
return 0;
}
如果分区2选择低、高和中的中位数作为轴,则轴应为5,结果应类似
2 1 1 3 4 2 5 9 7
然后我检查代码
if (a[i] < low_value) {
swap(a[i], a[index_low]);
counter++;
low_value=a[l];
}
else if(a[i]==low_value)
{
index_high++;
swap(a[i], a[index_high]);
}
if(a[i]
代码似乎试图找到数组的最小值,然后将它们移动到数组的开头。似乎是在进行选择排序,而不是快速排序。这解释了为什么当输入大小较大时速度较慢。如何进行基准测试?您确定当输入大小>10时,在main中进行随机快速排序调用需要2.2秒吗000?或者整个程序需要2.2秒?你是用-O2这样的标志编译的吗?@PetarPetrovic当输入大小在10000到100000之间时,时间差是非常明显的。我在Coursera自己的平台上测试了它,在那里它们指示时间。是的,我是用-O2标志编译的。我怀疑问题是分区2().I添加以下代码,参见枢轴位置分区2(a、l、r、I、j);如果(r-l>1000){std::cout感谢您的代码,但如果我知道我在哪里花费了这么多时间,以及如何减少时间,而不仅仅是复制您的解决方案,那将更有帮助。正如我所说,瓶颈是您选择数组中枢轴元素的方式。快速排序质量在很大程度上取决于这一时刻。然而,您始终可以使用尽管递归,它可能允许稍微减少时间。例如,更多信息请参见问题。附言:减少Nlog{3}(N)时间的愿望不幸的是,它面临着额外的开销。最有可能用三个子数组实现排序比用两个子数组实现排序要快得多——这是行不通的。至少这不容易。因此,这里有必要考虑一下——您需要难以置信的优化或可靠性。我不确定您运行的是哪一个代码,但我的代码运行得非常好,并且显示了正确的结果s、 如果您取消对print语句的注释,您会得到以下结果:1 1 2 3 4 5 7 9,甚至pivot也是正确的,即5。就这一点而言,“代码似乎试图找到数组的最小值,然后将它们移动到数组的开头。”就目前而言,数据集每次减少到一半之后partitioning@darkfall94我更新了我的ans。基本上我只是在main中调用了partition2一次来测试这个函数。如果你只是复制我的main并运行它,你会得到同样的结果吗?
if (a[i] < low_value) {
swap(a[i], a[index_low]);
counter++;
low_value=a[l];
}
else if(a[i]==low_value)
{
index_high++;
swap(a[i], a[index_high]);
}