C++ 快速排序实现
大家好,我是C++ 快速排序实现,c++,C++,大家好,我是C++新手,一直在潜心研究搜索和排序算法,并决定尝试编写自己的算法。以下是我的原型: void quicksort(int data[ ], size_t n); // Precondition: data is an array with at least n components. // Postcondition: The elements of data have been rearranged so // that data[0] <= data[1] <= .
C++
新手,一直在潜心研究搜索和排序算法,并决定尝试编写自己的算法。以下是我的原型:
void quicksort(int data[ ], size_t n);
// Precondition: data is an array with at least n components.
// Postcondition: The elements of data have been rearranged so
// that data[0] <= data[1] <= ... <= data[n-1].
void partition(int data[ ], size_t n, size_t& pivot_index);
// Precondition: n > 1, and data is an array (or subarray)
// with at least n elements.
// Postcondition: The function has selected some "pivot value"
// that occurs in data[0]..data[n-1]. The elements of data
// have then been rearranged, and the pivot index set so that:
// -- data[pivot_index] is equal to the pivot;
// -- Each item before data[pivot_index] is <= the pivot;
// -- Each item after data[pivot_index] is > the pivot.
void setPivot(int data[ ], size_t n);
// Precondition: n > 1 and data is an array or subarray
// Postcondition: data[0] holds the selected pivot value
// The original value of data[0] has been swapped with the selected pivot value
我已经开始函数定义:
void quicksort(int data[ ], size_t n)
// Library facilities used: cstdlib
{
size_t pivot_index; // Array index for the pivot element
size_t n1; // Number of elements before the pivot element
size_t n2; // Number of elements after the pivot element
if (n > 1)
{
// Partition the array, and set the pivot index.
partition(data, n, pivot_index);
// Compute the sizes of the subarrays.
n1 = pivot_index;
n2 = n - n1 - 1;
// Recursive calls will now sort the subarrays.
quicksort(data, n1);
quicksort((data + pivot_index + 1), n2);
}
}
void partition(int data[ ], size_t n, size_t& pivot_index)
// Library facilities used: algorithm, cstdlib
{
assert(n > 1);
setPivot(data, n);
}
void setPivot(int data[ ], size_t n)
// Library facilties used: algorithm, cstdlib
// This function chooses a pivot value as the median of three
// randomly selected values. The selected pivot is swapped with
// data[0] so that the pivot value is in the first position of the array
{
assert(n > 1);
}
我的问题是完成
void分区(int data[],size\t n,size\t&pivot\u index
和void setPivot(int data[],size\t n)的最佳方法是什么
关于速度?这是一个需要回答的有点棘手的问题,我喜欢你用双脚跳进去。因此,在构造编译器时,你根据一条指令与另一条指令相比所花费的时间单位来选择指令。尽管你可以使用Raymond的建议,只使用预先构造的代码,但你不会学到太多在比较排序算法中,最昂贵的两条指令是数组中的比较和交换,所以要最小化它们
我将首先讨论一个好的分区算法背后的数学问题。假设数据在数据[0 ]中,考虑最好的方法来最小化那些昂贵的掉期。
[34, 33, 9, 45, 1, -1, 9, -18, 75, 100]
一个好的分区可以最小化我们移动轴心的次数,因为我们不能最小化我们移动某物的次数(如果可以的话,我们就不会进行排序)
wall:=1
对于(i:=1;i数据[i]){
交换(数据、墙、i)
++墙
}
}
交换(数据,墙1,0)
枢轴指数:=墙-1
那么现在来回答为什么这是最有效的方法之一
void setPivot(int data[ ], size_t n)
index1:= rand_uniform()*n
index2:= rand_uniform()*n
index3:= rand_uniform()*n
mean:=(data[index1]+data[index2]+data[index3])/3
offset1:=abs(index1-mean)
offset2:=abs(index2-mean)
offset3:=abs(index3-mean)
if(offset1 < offset2 && offset1 < offset3)
swap(data,0,index1)
else if(offset2 < offset1 && offset2 < offset3)
swap(data,0,index2)
else if(offset3 < offset1 && offset3 < offset2)
swap(data,0,index3)
void setPivot(整数数据[],大小)
index1:=rand_uniform()*n
index2:=rand_uniform()*n
index3:=rand_uniform()*n
平均值:=(数据[index1]+数据[index2]+数据[index3])/3
抵销1:=abs(指数1平均值)
抵销2:=abs(指数2平均值)
抵销3:=abs(指数3平均值)
如果(偏移量1<偏移量2&&偏移量1<偏移量3)
交换(数据,0,索引1)
否则如果(偏移量2<偏移量1&&偏移量2<偏移量3)
交换(数据,0,index2)
否则如果(偏移量3<偏移量1&&偏移量3<偏移量2)
交换(数据,0,索引3)
应该清楚的是,这样做会有很多开销,但是setPivot的时间复杂度是恒定的,这意味着对于足够大的n来说,这样做会更快,因为选择的piviot在统计上会更频繁地将数据分成两个相等的部分,这是一个好的分治算法的全部要点thm.试试
std::partition
。太棒了!信息量非常大!那么您认为对于较大的数据库来说,快速排序是更快的选择吗?我知道,根据数据最初的排序方式,即升序到降序,或者至少是按一定顺序排序,那么其他排序方法是首选的?还是应该只使用快速排序@AlexChapman学习不同的排序算法是很好的,但是一旦你知道它们是如何工作的,你通常只需要使用标准库就可以做到这一点(例如,std::sort
)。我不会这么说,因为快速排序有O(nlog(n))最佳时间它本身就是最好的。它确实平均有一个很好的运行时间,并且这个使用智能枢轴选择的实现在最坏情况下运行的时间是O(n^2)是极不可能的。还有另一个排序算法利用了总是在O(nlog(n))中运行的堆时间公正地命名为HeapSort,这是你绝对应该检查的东西。如果你想得到真正的最佳,你可以计算出n个void分区的大小比void setPivot快,然后切换到一个简单的pivot选择。太棒了!谢谢@kryler,我感谢你提供的所有信息!
wall:=1
for(i:=1; i < n; ++i){
if(data[0]>data[i]){
swap(data, wall, i)
++wall
}
}
swap(data, wall-1, 0)
pivot_index:=wall-1
void setPivot(int data[ ], size_t n)
index1:= rand_uniform()*n
index2:= rand_uniform()*n
index3:= rand_uniform()*n
mean:=(data[index1]+data[index2]+data[index3])/3
offset1:=abs(index1-mean)
offset2:=abs(index2-mean)
offset3:=abs(index3-mean)
if(offset1 < offset2 && offset1 < offset3)
swap(data,0,index1)
else if(offset2 < offset1 && offset2 < offset3)
swap(data,0,index2)
else if(offset3 < offset1 && offset3 < offset2)
swap(data,0,index3)