C++快速排序透视优化
C++ QuickSort Pivot Optimization
目前,我有一个快速排序算法的准系统实现来对一些随机生成的数字进行排序。排序是有效的,比合并排序更有效。但是,对于特定的数字集(例如需要反向排序的反转数字(,我需要优化枢轴。
int* partition (int* first, int* last);
void quickSort(int* first, int* last) {
if (last - first <= 1) return;
int* pivot = partition(first, last);
quickSort(first, pivot);
quickSort(pivot + 1, last);
}
int* partition (int* first, int* last) {
int pivot = *(last - 1);
int* i = first;
int* j = last - 1;
for (;;) {
while (*i < pivot && i < last) i++;
while (*j >= pivot && j > first) j--;
if (i >= j) break;
swap (*i, *j);
}
swap (*(last - 1), *i);
return i;
}
因此,对于此代码,我要么要使用随机数作为分区步骤的透视,要么使用第一个、中间和最后一个元素的中位数作为枢轴。
我该怎么做?
我是排序算法的新手,我对它们的理解还没有完成。
只需更改以下行:
int pivot = *(last - 1);
…
swap ((last - 1), i);
像这样:
int* pos = (first + rand(last - first));
int pivot = *pos;
…
swap (pos, i);
或
int* pos = mean_of_three((last - 1), (first), ((first + last) / 2));
int pivot = *pos;
…
swap (pos, i);
其中mean_of_three
取 3 个指针并返回指向平均值的指针。
正如您已经提到的,选择数组的第一个或最后一个元素作为枢轴不是最佳实践,并且会导致算法落入 O(n^2(。透视选择算法的最佳选择取决于程序可能遇到的数据。如果数据有可能被排序或接近排序,那么随机透视是一个非常好的选择(并且非常容易实现(,以避免 O(n^2( 行为。另一方面,选择中间元素而不是第一个元素的费用是最小的,并且提供了针对排序数据的非常有效的保护。
再说一次,如果您确信您的数据不会被排序或几乎排序,那么中位数三分区策略似乎是最好的。
int PickPivotUsingMedian(int a[], int first, int last)
{
int mid = (first+ right)/2;
if (a[mid ] < a[first])
swap(&a[first],&a[mid ]);
if (a[last] < a[first])
swap(&a[first],&a[last]);
if (a[last]< a[mid ])
swap(&a[mid ],&a[last]);
swap(&a[mid], &a[last - 1]);//since the largest is already in the right.
return a[last - 1];
}
在数组边界内选择一个随机索引,并将该元素用作透视。
相关文章:
- 空基优化子对象的地址
- 关闭||运算符优化
- 如何解决gcc编译器优化导致的centos双编译器设置中的分段错误
- 返回值优化:显式移动还是隐式
- 人脸跟踪arduino代码的优化
- 使用仅使用一次的变量调用的复制构造函数.这可能是通过调用move构造函数进行编译器优化的情况吗
- 纯函数,为什么没有优化
- 为什么大多数 pair 实现默认不使用压缩(空基优化)?
- 如何以优化的方式同时迭代两个间距不相等的数组
- 小字符串优化(调试与发布模式)
- 浮点定向舍入和优化
- Visual Studio 调试优化如何工作?
- 为什么开关的优化方式与 c/c++ 中的链接不同?
- 线性优化目标函数中的绝对值
- GCC 会优化内联访问器吗?
- gcc 如何优化此循环?
- 如何防止 CUDA-GDB 中的<优化输出>值
- 为什么我的程序在 O0 和 O2 的优化级别返回不同的结果
- 这个C++编译器优化(在自身的实例上调用对象自己的构造函数)的名称是什么,它是如何工作的?
- C++快速排序透视优化