快速排序
简介
快速排序算是对冒泡排序的一种改进,也是属于交换排序里的一种。
基本思想
快速排序的基本思想是基于分治法:
在待排序的序列表 1-n 中,取一个元素 pivot 作为基准,通过一趟排序将待排序的序列表分为独立的两个部分,一个为 1 到 k-1,一个为 k+1 到 n ,使得前一个序列中所有元素均小于 pivot ,后一个序列所有元素均大于 pivot ,则 pivot 最终处在位置 k 上,这一过程称作一趟快速排序。而后,分别对每个子表再进行递归处理,重复上述过程,直至每个部分内只有一个元素或者为空。
代码示例
假设划分算法已知,记为Partition(),返回的是上述的 k 值。
void QuickSort(ElemType a[] , int low , int high){
if(low < high){ //递归跳出的条件
int pivotpos = Partition(a,low,high); //划分
QuickSort(a,low,pivotpos -1);//对基准元素左边序列进行递归排序
QuickSort(a,pivotpos +1,high);//对基准元素右边序列进行递归排序
}
}
下面是对Partition()函数具体代码
int Partition(ElemType a[] , int low , int high){
ElemType pivot = a[low];//将当前表中第一个元素设为枢轴值,对表进行划分
while(low < high){ //循环跳出条件
while(low < high && a[high] >= pivot) --high; //首先right指针从右至左扫描,直至找到比基准元素小的元素
a[low] = a[high]; //将比枢轴值小的元素与left指针交换
while(low < high && a[low] <= pivot) ++low;//left指针从左往右扫描,直至找到比基准元素大的元素
a[high] = a[low]; //将比枢轴值大的元素与right指针交换
}
a[low] = pivot; //枢轴元素存放到最终位置
return low; //返回存放枢轴值的最终位置
}
图解详释
性能分析
空间效率:
快速排序是递归的,需借助一个递归工作栈来保存每一层递归调用的必要信息,其容量应与递归调用的最大深度一致。最好情况为log₂(n+1);最坏情况是进行 n-1 次递归,所以深度为O(n);平均情况,深度为O(log₂n)。
时间效率:
当基准元素选为序列中最大或最小值时,为最坏情况
Cmax = 1+2+…+(n-1) = n*(n-1)/2 = O(n²)
当基准元素选为序列中的中值,为最好情况,时间复杂度为O(nlog₂n)
快速排序算法是所有内部排序算法中平均性能最优的排序算法!
稳定性
若右端区间存在两个关键字相同,且均小于基准值的记录,则在交换到左端区间后,他们相对位置发生变化,所以快速排序是一种不稳定的排序方法。
例如:
希望大家有所收获,一起学习。
若有错误,欢迎指正,谢谢。