快速排序
经典快速排序思想:找到一个数组的最后一个元素当作标准值,大于小于这个数的元素排在数组的左边,大于这个数的元素排在数组的右边,最后把大于数组的第一个元素和这个标准值进行交换。这时候算法的复杂度基于数据的有无序性,因为每次排序只能排好一个标准值的顺序,如果这个数据本来就是顺序或者逆序的就会导致O(n^2)的复杂度,如果每次正好取到中间数值的数字就是O(nlogn)的时间复杂度。
我们可以用荷兰国旗问题就行优化,定义less区域和more区域,每次可以将等于x的所有值排序完,减少循环次数:代码如下
void Swap(int &a,int &b) { if(a==b) return; a=a^b; b=a^b; a=a^b; } void QuickSort(int* &arr,int n) { if(n<2 || arr==NULL) return; Quicksort(arr,0,n-1); } void Quicksort(int* &arr,int l,int r) { if(l<r) {
//Swap(arr[r],arr[l+rand()%(r-l+1)]); int* p=Partition(arr,l,r); Quicksort(arr,l,p[0]-1); Quicksort(arr,p[1]+1,r); } } int* Partition(int* &arr,int l,int r) { int cur=l; int less=l-1; int more=r; while(cur<more) { if(arr[cur]>arr[r]) { Swap(arr[cur],arr[--more]); } else if(arr[cur]<arr[r]) { Swap(arr[cur++],arr[++less]); } else { cur++; } } Swap(arr[r],arr[more]); int *p=(int *)malloc(sizeof(int)*2); p[0]=less+1; p[1]=more; return p; }
因为依赖数据状况,这时候我们就可以利用随机快排来忽略数据状况,即每次选取的值是一个随机位置上的值,可以在数学期望上达到O(nlogn)的时间复杂度。
Swap(arr[r],arr[l+rand()%(r-l+1)]);
格外的空间复杂度是O(logn),因为在随机快排上每次循环需要两个变量记录相等区间的首位置和末位置,而循环次数也是在概率,在期望上是O(logn)。

浙公网安备 33010602011771号