快速排序的一些实现技巧(曾经被手写快排打倒过n+1次。。。)
来源:互联网 发布:owncloud 源码 编辑:程序博客网 时间:2024/05/16 00:07
首先是一个最简单的版本,与常见的双向扫描相比,这个只需要单向扫描即可,不容易出错,推荐手写时优先选择。m位置左侧包括m位置本身,是小于分割元素的,m位置右侧位置,是大于等于分割元素的。
#include<iostream>using namespace std;void qsort(int l,int r,int a[]){ if(l>=r) { return; } int m=l; for(int i=l+1;i<=r;++i) { if(a[i]<a[l]) { ++m; int t=a[m]; a[m]=a[i]; a[i]=t; } } int tmp=a[l]; a[l]=a[m]; a[m]=tmp; qsort(l,m-1,a); qsort(m+1,r,a);}int main(){ int a[]={8,5,7,4,9,2,1,0,4,5,1,2,8,5}; int n=sizeof(a)/sizeof(a[0]); qsort(0,n-1,a); for(int i=0;i<n;++i) { cout<<a[i]<<" "; } cout<<endl;}
但上述代码在处理特殊情况时效率会非常糟糕,比如数组含有n个相同的元素,此时由于上述处理相同元素的做法会得到一颗非常不平衡的递归树,这样将运行时间增加到O(n^2)。
这可以通过使用双向扫描并采用恰当的处理相同元素的策略来解决,代码如下:
void qsort2(int l,int r,int a[]){ if(l>=r) { return ; } int tmp=a[l]; int i=l; int j=r+1; while(true) { do { ++i; }while((i<=r)&&(a[i]<tmp)); do { --j; }while(a[j]>tmp);//no need to check j>l,because at most when j==l,a[j] will equal tmp if(i>j) { break; } int tmp=a[i]; a[i]=a[j]; a[j]=tmp; } a[l]=a[j]; a[j]=tmp; qsort2(l,j-1,a); qsort2(j+1,r,a);}
在排序含有大量相同元素的序列时,这个方法的效率会显著高于第一个方法,因为可以避免陷入最坏O(n^2)的境地。
此外,需要注意的是划分点的选择也是一门技术活。上述讨论基于序列中的元素都是随机排列的这一假设。如果序列是已经有序的,那么上述无论哪个方法都会陷入O(n^2)的尴尬境地(因为划分的递归树是严重不平衡的),解决方案是随机选取划分点,之后将划分点钟元素与第一个元素交换,剩下的就和上述选择第一个元素作为划分点没有什么区别了。
0 0
- 快速排序的一些实现技巧(曾经被手写快排打倒过n+1次。。。)
- 快速排序的实现(快排)
- 快速排序(快排)算法的C++两种实现
- 快速 排序的思想并实现一个快排?
- 快速排序(快排)的一些细节和k-th问题
- Java实现常见的排序算法之快排(快速排序)
- 快速排序(Java随机位置快排实现)
- 快排 快速排序
- 快速排序 改进快排的方法
- 快速排序 改进快排的方法
- 快速排序 改进快排的方法
- 快排函数(手写)
- 快排,堆排序,基数排序手写记录
- QuickSort/快速排序/快排
- 快速排序算法(快排)
- [算法]快排-快速排序
- Java 快速排序 快排
- [模板]快速排序(快排)
- URAL 1502. Domino Dots(数学)
- MVC 5使用ViewData(对象)显示数据
- 15 第三周项目5——数组作数据成员
- 摆脱ViewHolder,一种无需ViewHolder的高效ListView写法
- ftp服务安装与配置
- 快速排序的一些实现技巧(曾经被手写快排打倒过n+1次。。。)
- 关于数学公式输入中括号的换行问题 的两种常用方法
- android 颜色
- MVC 5使用ViewData(模型)显示数据
- nyoj 88 汉诺塔(一)
- 关于我的博客
- 第三周 项目二:分数类的雏形
- 取整
- MVC 5使用ViewBag(对象)显示数据