快速排序及三向切分快排——java实现
快速排序也是一种分治算法。主要思想是选取一个切分点,将大于切分点的元素都放置到数组右侧,小于切分点的元素都放置到数组左侧;然后递归,再对切分点左侧和右侧分别排序。
归并排序时递归在前,归并在后,快速排序是切分在前,排序在后。
快速排序的运行时间在1.39nlogn的某个常数因子范围之内,归并排序也能做到这一点,但是快速排序更快,因为它的移动次数更少。
快速排序的关键点在于切分点的选取,对于正好逆序的情况,它的复杂度达到了n2,而且与归并排序相比不稳定。
为了防止最坏情况的出现,一般在排序前先将元素随机打乱。
package 排序; import edu.princeton.cs.algs4.In;
import edu.princeton.cs.algs4.StdOut;
import edu.princeton.cs.algs4.StdRandom;
/**
* @author evasean www.cnblogs.com/evasean/
*/
@SuppressWarnings("rawtypes")
public class Quick快速排序 {
private static int partition(Comparable[] a, int lo, int hi){
int i = lo;
int j = hi+1;
Comparable v = a[lo];//切分元素
while(true){
while(less(a[++i],v))
if(i==hi) break;
while(less(v,a[--j]))
if(j==lo) break;
if(i>=j) break;
exch(a,i,j);
}
exch(a,lo,j);//此时j<=i,且v > a[j],将切分元素v放入正确位置
return j;
}
public static void sort(Comparable[] a){
StdRandom.shuffle(a); //消除最坏的情况
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);
} @SuppressWarnings("unchecked")
private static boolean less(Comparable v, Comparable w){
return v.compareTo(w) < 0;
}
private static void exch(Comparable[] a, int i, int j){
Comparable t = a[i];
a[i] = a[j];
a[j] = t;
}
private static void show(Comparable[] a){
for(int i=0; i<a.length; i++) StdOut.print(a[i] + " ");
StdOut.println();
}
public static boolean isSorted(Comparable[] a){
for(int i = 1; i < a.length; i++){
if(less(a[i],a[i-1])) return false;
}
return true;
}
public static void main(String[] args){
String[] a = new In().readAllStrings();
sort(a);
assert isSorted(a);
show(a);
}
}
实际应用中经常会出现大量重复元素的排序情况,而快速排序在面对重复元素时排序复杂度并没有降低。Dijkstra提出的三向切分快速排序方法可以迅速降低这种情况下的复杂度,甚至有可能达到线性级别n,如荷兰国旗问题(见我的另一篇文章)。其基本思想就是选取切分点v,从左到右遍历,维护一个从前往后遍历的位置点lt,使得a[0]~a[lt-1]都小于v,维护一个从前往后遍历的位置点i,使得a[lt]~a[i-1]都等于v,维护一个从后往前的位置点,使得a[i]~a[gt]都大于v。
/*
* 三向切分的快速排序
* a[lo...lt-1]中的元素都小于v
* a[gt+1....hi]中的元素都大于v
* a[lt...i-1]中的元素都等于v
* a[i...gt]中的元素都还未确定,通过下面处理
* 1. a[i]小于v,将a[lt]和a[i]交换,将lt和i加1
* 2. a[i]大于v,将a[gt]和a[i]交换,将gt减1
* 3. a[i]等于v,将i加1
* 这些操作都会保证数组元素不变且缩小gt-i的值,这样循环才会结束
*/
private static void sort3way(Comparable[] a, int lo, int hi){
if(hi <= lo) return;
int lt = lo;
int i = lo+1;
int gt = hi;
Comparable v = a[lo];
while(i <= gt){
int cmp = a[i].compareTo(v);
if(cmp<0) exch(a,lt++,i++);
else if(cmp>0) exch(a,i,gt--);
else i++;
}//现在a[lo...lt-1] < v=a[lt...gt]<a[gt+1...hi]
sort3way(a,lo,lt-1);
sort3way(a,gt+1,hi);
}
用这里的sort3way方法替代快速排序中的sort(Comparable[] a, int lo, int hi)即可。
快速排序及三向切分快排——java实现的更多相关文章
- 快速排序详解(lomuto划分快排,hoare划分快排,classic经典快排,dualpivot双轴快排源码)
目录 快速排序(lomuto划分快排,hoare划分快排,classic经典快排,dualpivot双轴快排) 一.快速排序思想 二.划分思想 三.测试用例 快速排序(lomuto划分快排,hoare ...
- 快排+java实现
import java.util.Arrays; public class QuickSort { //三数取中法.取出不大不小的那个位置 public static int getPivotPos( ...
- 数据结构65:快速排序算法(QSort,快排)
上节介绍了如何使用起泡排序的思想对无序表中的记录按照一定的规则进行排序,本节再介绍一种排序算法——快速排序算法(Quick Sort). C语言中自带函数库中就有快速排序——qsort函数 ,包含在 ...
- 快排java实现
package sort; public class QuickSort { public static final int cutoff = 3; /** * insertion sort * * ...
- 快排java代码
定一个基准位,递归左右两边排序. public void fun(){ int arr[] = {2,3,4,5,6,7,822,3,4,5,8,6,5,4,2,1}; //System.out.pr ...
- 记录一个基于Java的利用快排切分来实现快排TopK问题的代码模板
使用快排切分实现快排和TopK问题的解题模板 import java.util.Arrays; public class TestDemo { public static void main(Stri ...
- 快速排序 java实现 (原理-优化) 三路快排
一.基本的快速排序 在数组中选取一个元素为基点,然后想办法把这个基点元素移动到它在排好序后的最终位置,使得新数组中在这个基点之前的元素都小于这个基点,而之后的元素都大于这个基点,然后再对前后两部分数组 ...
- Quick Sort(三向切分的快速排序)(Java)
//三向切分的快速排序 //这种切分方法对于数组中有大量重复元素的情况有比较大的性能提升 public static void main(String[] args) { Scanner input ...
- Java基础进阶:APi使用,Math,Arrarys,Objects工具类,自动拆装箱,字符串与基本数据类型互转,递归算法源码,冒泡排序源码实现,快排实现源码,附重难点,代码实现源码,课堂笔记,课后扩展及答案
要点摘要 Math: 类中么有构造方法,内部方法是静态的,可以直接类名.方式调用 常用: Math.abs(int a):返回参数绝对值 Math.ceil(double a):返回大于或等于参数的最 ...
随机推荐
- db2 jdbc连接字符串中 指定currentSchema
场景:连接DB2数据库的,jdbc的连接字符串中没有给当前的数据源用户指定默认的schema,而当前的数据源用户下可能有多个schema,则会使用数据源用户默认的schema. 例如:admin用户的 ...
- RTL Compiler之Example
Synthesis = Translation + Logic Optimization + Mapping Step 1 Source files 1) make directory mkdir ...
- 【转载】HTTP 缓存的四种风味与缓存策略
原文地址:https://segmentfault.com/a/1190000006689795 HTTP Cache 通过网络获取内容既缓慢,成本又高:大的响应需要在客户端和服务器之间进行多次往返通 ...
- 06--ubuntu的sqlite安装
知道学习嵌入式技术,数据库是必须懂的,看的书上嵌入式的教程都在用,看来我是非学不可了,下面就简单的记录一下我在Ubuntu 12.04系统上安装 SQLite 的过程以及使用. 相关阅读: SQLit ...
- java主要集合类的数据结构
1).ArrayList ArrayList维护着一个对象数组.如果调用new ArrayList()后,它会默认初始一个size=10的数组. 每次add操作都要检查数组容量,如果不够,重新 ...
- js输出非字符串,非null值
console.log(!"");//非空(true) console.log(!);//非0(true) console.log(!" ");//非空格(fa ...
- eclipse版本和jdk的版本兼容问题
eclipse也是有版本的,当版本过低时,无法兼容高版本的jdk 项目中用的是jdk1.8,但是低版本的eclipse只能选到jdk1.7,导致java文件在编译的过程中,不识别1.8版本jdk的语法 ...
- shouldComponentUpdate不能直接比较object
凡是参阅过react官方英文文档的童鞋大体上都能知道对于一个组件来说,其state的改变(调用this.setState()方法)以及从父组件接受的props发生变化时,会导致组件重渲染,正所谓&qu ...
- GeckoWebBrowser设置cookie
var uri = new Uri("http://www.aa.com"); //often cookies are stored on domain level, so &qu ...
- Linux之网络文件共享服务(FTP)
一.FTP概念 •File Transfer Protocol 早期的三个应用级协议之一 •基于C/S结构 •双通道协议:数据和命令连接 •数据传输格式:二进制(默认)和文本 •两种模式:服务器角度 ...