快速排序(C++) – 优不优化两个世界
快速排序是一个O(nlogn)的算法,这个算法优化好后在综合性能上是相当优秀的,不进行优化或者优化不好会慢到怀疑人生,因为一不小心就会退化成O(n2)的算法;所以可以这么说,别的算法可能优不优化都能用,快速排序是不优化没法用;
快速排序与归并排序一样用到的也是分治的算法思路,或者说二分法,不同的是归并排序的拆分和合并一定是2的倍率,而快速排序则不一定是拆分成一半+一半(最好的情况),也可能是一个+一大堆(最差的情况),这也就是为什么快速排序一不小心会退化成O(n2)算法的原因;
快速排序算法思路是一开始先找一个元,然后将元放到最左或最右,当然也可以直接找最左或最右作为元,然后逐个元素与元进行比较,比元小的放在左边,比元大的放在右边,都比较完后,将元放到比其小的部分和比其大的部分的中间位置,这样这个元的位置就ok了,然后递归进行左边和右边的快速排序;下面会涉及到几种快速排序的思路,基本就是不断优化的过程,玩法各不相同,主体思路一致~~
快速排序 – 基本玩法
基本玩法每次以序列最左边的元素作为元,然后进行与逐个元素进行比较,比元小的放在左边,比元大的放在右边,然后将元放到正确位置上,然后递归进行;
这个是纯基本玩法,未进行任何优化,虽然在面对随机序列时能做到O(nlogn)的级别,但是还是较慢的,而且对于基本有序和元素大量重复的序列时会降级成O(n2)的级别
// quickSort为接口,__quickSortBasic为实际快速排序方法
// 对arr[l...r]部分进行快速排序
template <typename T>
void __quickSortBasic(T arr[], int left, int right){
// left>=right时,所有元素已排好序,返回,结束排序
if( left >= right )
return;
// 以最左边的元素为元
T pivot = arr[left];
// j代表的是小于元的部分(左边部分)的右边界的下标
// arr[left+1...j] < pivot ; arr[j+1...i) > pivot
int j = left;
// 遍历每个元素,因为最左边元素为元,所以从left+1开始遍历
// i代表的遍历到的元素序号
for( int i=left+1; i<=right ; i++ )
// 如果由元素小于元,则将左边部分的右边界+1,然后将这个小的元素放到左边部分的右边界
if( arr[i] < pivot ){