我一直在尝试用C++编写一个模板化函数,它可以接受任何类型的数组并对其进行排序。使用的排序必须是快速排序或合并排序,但我在实现这两种排序时遇到了很多麻烦,因为快速排序头通常带有顶部和底部参数,合并排序则带有第一个和最后一个参数。我的函数头如下:void mySort(T*array,int n)
到目前为止,我有这个:
template <typename T>
void sort(T *a, int n)
{
int i = 0;
int j = n-1;
int tmp;
int pivot = a[(n-1)/2];
while (i <= j){
while (a[i] < pivot)
i++;
while (a[j] > pivot)
j--;
if (i<=j){
tmp = a[i];
a[i] = a[j];
a[j] = a[i];
i++;
j--;
}
}
if(0<j)
sort(a, j);
/*
if(i<right)
sort(
*/
}
我试图使用递归调用进行排序,但我不知道如何在没有不同参数列表的情况下为创建的正确分区调用递归。
在回答实际问题之前:您的代码将受益于将分区代码从函数体中分解出来!这样,您就可以调用分区来确定要调用的两个数组之间的中点,也就是说,您会得到这样的东西:
template <typename T>
void sort(T* a, int n) {
T* mid = partition(a, n);
// ...
}
其思想是[a, mid)
包含排序小于枢轴的所有元素,而[mid, a + n)
包含排序等于或大于枢轴的所有元件。剩下的都是
用两个数组递归调用
sort()
,即sort(a, mid - a); sort(mid, (a + n) - mid);
如果获得的数组小于2,请确保
sort()
终止。
当然,如果你想让你的快速排序是快速,你还需要掌握六个左右的技巧。类似:
- 使用Introsort确保复杂性为
O(n lg n)
(例如与Merge Sort一起使用) - 对小范围使用插入排序
- 使用分区和插入排序的实现,利用适当的哨兵
- 排序实际上是直接对范围进行排序
奇怪的是,选择一个支点是徒劳的。据我所知,使用中间元素和任何更高级的技术一样有效(假设实现了上面提到的优化)。
将调用的函数与递归函数分离:
// recursive function
template <typename T>
void quicksort(T *a, int lo, int hi)
{
// ...
}
// called function
template <typename T>
void sort(T *a, int n)
{
if(n < 2)return;
quicksort(a, 0, n-1);
}