快速排序
2016-06-05 22:42
399 查看
快速排序
实现原理:递归的将切分元素的左边和右边排序,优点是原地排序,而且速度快,时间复杂度是线性对数的import edu.princeton.cs.algs4.StdOut; import edu.princeton.cs.algs4.StdRandom; public class Quick { public static void sort(Comparable[] a){ StdRandom.shuffle(a); //消除对输入的依赖,保持随机性的另一种方法是在partition中随机选取一个切分元素 sort(a, 0, a.length - 1); } private static void sort(Comparable[] a, int lo, int hi){ if(hi <= lo) return; int j = partition(a, lo, hi); sort(a, lo, j - 1); //将左半部分排序 sort(a, j + 1, hi); //将有半部分排序 } private static int partition(Comparable[] a, int lo, int hi) { // TODO Auto-generated method stub int i = lo, j = hi + 1; Comparable v = a[lo]; while(true){ while(less(a[++i],v)) //获得比v大的数 if(i == hi) break; while(less(v, a[--j])) //获得比v小的数 if(j == lo) break; if(i >= j) //当i和j相遇时退出循环 break; exch(a, i, j); } exch(a, lo, j); return j; } private static void exch(Comparable[] a, int i, int j) { // TODO Auto-generated method stub Comparable t = a[i]; a[i] = a[j]; a[j] = t; } private static boolean less(Comparable v, Comparable w) { // TODO Auto-generated method stub return v.compareTo(w) < 0; } public static void show(Comparable[] a) { // TODO Auto-generated method stub for(int i = 0; i <a.length;i++ ) StdOut.print(a[i] + " "); StdOut.println(); } }
但是当数组过小时,快速排序的性能并不见得回比插入排序好,所以在递归时,判断数组大小是否小于某一个合适的常数,当小于这个常数时使用插入排序。将私有方法sort()进行改进。其他部分保持不变。
改进代码如下:
private static void sort(Comparable[] a, int lo, int hi){ if(hi <= lo + 10){ //对于小数组使用插入排序性能比快速排序更好 Insertion.sort(a, lo, hi); return; } int j = partition(a, lo, hi); sort(a, lo, j - 1); //将左半部分排序 sort(a, j + 1, hi); //将有半部分排序 }
上面的优化解决了当数组过小时,性能较差的问题,但是当数组中重复元素很多时,快速排序任然会把大量时间话在对相等元素进行排序,下面这段代码是想了三向切分快速排序。它将数组分为小于切分元素,等于切分元素,大于切分元素三个部分,然后对小于和大于的部分进行排序,而等于的部分不动。
import edu.princeton.cs.algs4.StdOut; import edu.princeton.cs.algs4.StdRandom; public class Quick3way { public static void sort(Comparable[] a){ StdRandom.shuffle(a); //消除对输入的依赖,保持随机性的另一种方法是在partition中随机选取一个切分元素 sort(a, 0, a.length - 1); } private static void sort(Comparable[] a, int lo, int hi) { // TODO Auto-generated method stub if(hi <= lo) return; int lt = lo,i = lo + 1, gt = hi; //a[lo...lt-1]小于v,a[lt...i-1]等于1,a[i...gt]不确定,a[gt+1...hi]大于1 Comparable v = a[lo]; while(i <= gt){ int cmp = a[i].compareTo(v); if(cmp < 0) exch(a,lt++, i++); //将a[lt]和a[i]交换 else if(cmp > 0) exch(a, i, gt--); //i不需要在进行自增操作,因为a[gt]这个元素还没有和v比较 else i++; } sort(a, lo, lt - 1); //对小于v的元素进行排序 sort(a, gt + 1, hi); //对大于v的元素进行排序 } private static void exch(Comparable[] a, int i, int j) { // TODO Auto-generated method stub Comparable t = a[i]; a[i] = a[j]; a[j] = t; } private static boolean less(Comparable v, Comparable w) { // TODO Auto-generated method stub return v.compareTo(w) < 0; } public static void show(Comparable[] a) { // TODO Auto-generated method stub for(int i = 0; i <a.length;i++ ) StdOut.print(a[i] + " "); StdOut.println(); } }
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序