快速排序算法及优化

xiaoxiao2025-11-20  8

1,简单快速排序,

void Math_Qucik_Sort(T array[], int len) { srand(time(NULL)); Quick_Sort(array, 0, len - 1); } template <typename T> void Quick_Sort(T array[], int l, int r) { if (l - r <= 15) { Math_Insert_Sort(array, l, r); return; } int p = partition2(array, l, r); Quick_Sort(array, l, p - 1); Quick_Sort(array, p+1, r); } int partition(T array[], int l, int r) { T v=array[l]; int j = l; //array[l+1,j]<v array[j+1,i)>v,i即为需要判断的地方 for (int i = l + 1; i <= r; i++) {//都为空 if (array[i] < v) { swap(array[j+1], array[i]); j++; } } swap(array[j], array[l]); return j; }

算法说明

快速排序:几个重要数据,对应到partition中的变量 v:标志位,取第一个 [l+1,j]<=v 条件1 [j+1,i)>v 条件2 i从[l+1,r],是当前需要判断的值 如果,array[i]>v,不需要移动,i++ 如果相反情况,将array[i]与array[j+1]交换 i++,array[j+1]是大于v的,条件2满足 j++,array[i]<=v,条件1满足 这样到最后,保证,[l+1,j]<=v,[j+1,r]>v v是属于前者的,将v和array[j]替换,返回j(j左右满足条件,左边<=,右边>) 递归成立

2,问题1,假设数组时基本有序,那么j一侧的数量会远大于另一侧。

如果就是有序的,那么相当于O(n^2)次运算。

优化1

srand(time(NULL)); swap(array[l], array[rand() % (r - l + 1) + l]); T v = array[l]; //标志位取随机的位置

3,问题2,假设数组差距较小,比如全部属于[0-10],那么有大量相等,也会导致一侧远大于另一侧。

优化

int partition2(T array[], int l, int r) { swap(array[l], array[rand() % (r - l + 1) + l]); T v = array[l]; ;//arr[l+1,i) <=v arr(j,r]>=v; int i = l + 1, j = r; while (true) { while (i<=r && array[i] < v) i++; while (j >= l + 1 && array[j] > v) j--; if (i >j) { break; } /* 如过出现i=j取相等,那么相等时,这个值等于v 如果>,取j,这是j为最后一个小于v的值 */ swap(array[i], array[j]); i++; j--; } swap(array[l], array[j]);//l 这个位置小于array[l]的 return j; }

说明

从两侧开始遍历, [l+1,i)<v (j,r]>v 保持这样的条件进行遍历, 左侧碰到相等,会放到右侧 右侧碰到相等,放到左侧 将相等的值,分到两侧

4,还可以分三段排序

template<typename T> void Math_Qucik_Sort_3Ways(T array[], int l, int r) { /*小于等于大于*/ if (l >= r) { return; } swap(array[l], array[rand() % (r - l + 1) + l]); T v = array[l]; // l < lt = gt i > r int lt = l; //[l+1,lt]<v int gt = r + 1;//[gt .. r]>v int i = l + 1; //[lt+1,i)==v while (i < gt) { if (array[i] < v) { swap(array[i], array[lt + 1]); lt++; i++; }//放到第一个区间最后一部分 else if (array[i] > v) { swap(array[i], array[gt - 1]); gt--; } else { i++; } } swap(array[l], array[lt]); Math_Qucik_Sort_3Ways(array,l, lt-1); Math_Qucik_Sort_3Ways(array,gt, r); }

分大于等于小于三部分。

总结,O(nlogn)这种算法,但是分为logn层,每层n的时间复杂的。对于快排来说,每次不是均分,可能会导致实际会大于logn层。

 

 

 

转载请注明原文地址: https://www.6miu.com/read-5039999.html

最新回复(0)