4 -- 交换排序之快速排序
2015-05-28 14:48
218 查看
四、快速排序算法
快速排序是冒泡排序的一种改进,冒泡排序排完一趟最大值冒出来了,那么可不可以先选定一个值,然后扫描待排序序列,把小于该值得记录和大于该值得记录分成两个单独的序列,然后分别对这两个序列进行上述操作。我们把选定的值作为枢纽值,如果枢纽值为序列中的最大值,那么一趟快速排序就变成了一趟冒泡排序。
快速排序时间与划分是否对称有关。快速排序的平均时间复杂度为o(n*logn),至于为什么是o(n*logn),请参考《算法导论》第7章,书中用递归树的方法阐述了快速排序平均时间。且常数因子很小,所以就平均时间而言,快速排序是很好的内部排序方法。最佳情况下(每次划分都对称)时间复杂度o(n*logn)。最坏情况下(每次划分都不对称,如输入的序列有序或者逆序时)时间复杂度为o(n^2),所以在待排序序列有序或逆序时不宜选用快速排序。此外,快速排序是不稳定的。
最佳情况下,每次划分都是对称的,由于枢纽值不再考虑,所以得到的两个子问题的大小不可能大于n/2,同时一趟快速排序时间为o(n),所以运行时间递归表达式:
T(n)<=2T(n/2)+o(n)。这个递归式的解法请参考下一篇博客中归并排序效率分析。其解为T(n)=o(n*logn)。
最坏情况下,每次划分都很不对称,T(n)=T(n-1)+o(n),可以用递归树来解,第i层的代价为n-i+1.总共有n层。把每一层代价加起来有n-1个n相加。所以这个递归式的解为T(n)=o(n^2),此时就是冒泡排序。
//递归排序,双向扫描
public void quickSort1(int a[], int low, int high){
//low作为枢纽值,把小于该值和大于该值分成两个记录
if(low>a.length||high>a.length||low<0||high<0)return;
if(low>=high)return ;
int pivotkey = a[low];
int i=low, j=high;
//双向扫描
while(i<j){
//i位置是pivotkey,先找到大于pivotkey的放在pivotkey得位置,不会覆盖其他值,
//然后找到一个大于pivotkey的值a[i]放在j的位置。然后pivotkey放在i的位置
while(i<j&&a[j]>=pivotkey){
j--;
}
a[i]=a[j];
while(i<j&&a[i]<=pivotkey){
i++;
}
a[j]=a[i];
}
a[i]=pivotkey;
//递归出小于该值得记录
quickSort1(a, low, i-1);
//递归出大于该值得记录
quickSort1(a, i+1, high);
}
快速排序是冒泡排序的一种改进,冒泡排序排完一趟最大值冒出来了,那么可不可以先选定一个值,然后扫描待排序序列,把小于该值得记录和大于该值得记录分成两个单独的序列,然后分别对这两个序列进行上述操作。我们把选定的值作为枢纽值,如果枢纽值为序列中的最大值,那么一趟快速排序就变成了一趟冒泡排序。
快速排序时间与划分是否对称有关。快速排序的平均时间复杂度为o(n*logn),至于为什么是o(n*logn),请参考《算法导论》第7章,书中用递归树的方法阐述了快速排序平均时间。且常数因子很小,所以就平均时间而言,快速排序是很好的内部排序方法。最佳情况下(每次划分都对称)时间复杂度o(n*logn)。最坏情况下(每次划分都不对称,如输入的序列有序或者逆序时)时间复杂度为o(n^2),所以在待排序序列有序或逆序时不宜选用快速排序。此外,快速排序是不稳定的。
最佳情况下,每次划分都是对称的,由于枢纽值不再考虑,所以得到的两个子问题的大小不可能大于n/2,同时一趟快速排序时间为o(n),所以运行时间递归表达式:
T(n)<=2T(n/2)+o(n)。这个递归式的解法请参考下一篇博客中归并排序效率分析。其解为T(n)=o(n*logn)。
最坏情况下,每次划分都很不对称,T(n)=T(n-1)+o(n),可以用递归树来解,第i层的代价为n-i+1.总共有n层。把每一层代价加起来有n-1个n相加。所以这个递归式的解为T(n)=o(n^2),此时就是冒泡排序。
//递归排序,双向扫描
public void quickSort1(int a[], int low, int high){
//low作为枢纽值,把小于该值和大于该值分成两个记录
if(low>a.length||high>a.length||low<0||high<0)return;
if(low>=high)return ;
int pivotkey = a[low];
int i=low, j=high;
//双向扫描
while(i<j){
//i位置是pivotkey,先找到大于pivotkey的放在pivotkey得位置,不会覆盖其他值,
//然后找到一个大于pivotkey的值a[i]放在j的位置。然后pivotkey放在i的位置
while(i<j&&a[j]>=pivotkey){
j--;
}
a[i]=a[j];
while(i<j&&a[i]<=pivotkey){
i++;
}
a[j]=a[i];
}
a[i]=pivotkey;
//递归出小于该值得记录
quickSort1(a, low, i-1);
//递归出大于该值得记录
quickSort1(a, i+1, high);
}
相关文章推荐
- 4 -- 交换排序之快速排序
- 【算法之家】——交换排序之冒泡排序与快速排序
- 每天一个小程序(15)——交换排序之快速排序
- 数据结构例程—— 交换排序之快速排序
- 交换排序之快速排序
- 交换排序之快速排序
- 交换排序:起泡排序 快速排序
- 内部交换排序---快速排序
- 交换排序之--冒泡排序,快速排序
- 交换排序之快速排序原理、源码及时间、空间复杂度
- 交换排序算法---冒泡排序与快速排序
- 【交换排序】快速排序
- 交换排序之快速排序(java实现)
- 排序算法--交换排序之快速排序
- Java实现交换排序 之 冒泡排序和快速排序
- 图解"数据结构--内部排序算法"----交换排序:冒泡排序、快速排序
- 20180316交换排序-快速排序
- 排序算法五:交换排序之快速排序
- 8)排序①排序算法之交换排序[2]快速排序
- 【交换排序】 - 快速排序