概述
一 概述
快速排序也是交换排序中的一种,它基于分治的思想:在待排序表L[1 ... n]中任取一个元素pivot作为基准,通过一趟排序将待排序表划分为独立的两部分L[1 ... k-1]和L[k ... n],使得L[1 ... k-1]中的所有元素小于privot,同时L[k+1 ... n]中的所有元素大于等于pivot,则pivot放在了其最终位置上,这个过程称为一趟快速排序(或一次划分)。然后分别递归地对两个子表重复上述过程,直至每部分内只有一个元素或空为止。即所有元素放在了其最终位置上。
二 快速排序的过程
一趟快速排序的过程是一个交替搜索和交换的过程,如序列49 38 65 97 76 13 27 49,设置两个指针分别指向头部和尾部。取第一个元素49为基准值并将其赋值给pivot。
三 代码实现快速排序
#include<stdio.h>
int Partitions(int a[], int low, int high){
int pivot = a[low]; //将当前表中的第一个元素设置为基准值,对表进行划分
while(low < high) { //循环跳出条件
while(low < high && a[high] >= pivot) --high;
a[low] = a[high]; //将小于基准值的元素移动到左端
while(low < high && a[low] <= pivot) ++low;
a[high] = a[low]; //将大于基准值的元素移动到右端
}
a[low] = pivot;
return low; //返回存放基准值的最终位置
}
void QuickSort(int a[], int low, int high){
if(low < high){ //递归跳出的条件
int partition = Partitions(a,low,high);
QuickSort(a,low,partition-1); //递归小的部分
QuickSort(a,partition+1,high);//递归大的部分
}
}
int main() {
int b[] = {-1,49,38,65,97,76,13,27,49};
QuickSort(b,1,8);
for(int i = 1; i < 9; i++) {
printf("%d ",b[i]);
}
return 0;
}
异常:
原因:将Partitions(int a[],int low,int high)函数放在QuickSort(int a[],int low,int high)之后声明于实现。
结果展示:
四 算法性能分析
算法 | 最好时间 | 最坏时间 | 平均时间 | 额外空间/空间复杂度 | 稳定性 |
---|---|---|---|---|---|
快速插入排序 | O(nlog2^n) | O(n^2) | O(nlog2^n) | O(log2^n) | 不稳定 |
空间效率:由于快速排序是递归的,需要借助一个递归工作栈来保存每层递归调用的必要信息,其容量应与递归调用的最大深度一致,最好情况下为O(log2^n);最坏情况下,因为要进行n-1此递归调用,所以栈的深度为O(n);在平均情况下,栈的深度为O(log2^n)。
时间效率:快速排序的运行时间与划分是否对称有关,快速排序的最坏情况发生在两个区域分别包含n-1个元素和0个元素,这种最大程度上的不对称若发生在每层递归上,即对应于初始排序表基本有序或基本逆序时,就得到了最坏情况下的时间复杂度为O(n^2)。
提高算法效率的方法:尽量选取一个可以将数据中分的基准元素,如从序列的头尾及中间选取三个元素,再取这三个元素的中间值作为最终的基准值,或者是随机地从当前表中选取基准元素,这样作可以使得最坏情况在实际排序中几乎不会发生。
稳定性:在划分算法中,若右端区间有两个相同的关键字,且均小于基准值的记录,则在交换的左端区间后,它们的相对位置会发生变化,即快速排序算法不是一种稳定的排序算法。如表L = {3,2,2},经过一趟排序后L = {2,2,3},显然,2与2的相对次序已经发生了变化。
最后
以上就是沉静斑马为你收集整理的快速排序的全部内容,希望文章能够帮你解决快速排序所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复