快速排序及三向切分快排——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):返回大于或等于参数的最 ...
随机推荐
- nginx-配置反向代理实例
nginx反向代理配置及优化 2009-05-26 作者:守住每一天blog:liuyu.blog.51cto.combbs:bbs.linuxtone.orgmsn:liuyubj520#hotma ...
- Linux 开启443端口
1 在Linux终端输入指令: iptables -I INPUT -p tcp --dport 443 -j ACCEPT 2 回车之后继续输入指令,输入保存防火墙配置指令: service ...
- Notepad++运行JAVA代码
第一种方法: 工具栏->运行 点击后选择运行 1.在运行窗口中输入: cmd /k javac "$(FULL_CURRENT_PATH)" & echo 编译成功 ...
- EF 配置
DbContext public class ZSZDbContext : DbContext { //ILog ILogger 容易混淆 private static ILog log = LogM ...
- Python----递归------Eight Queens 八皇后问题
递归思想是算法编程中的重要思想. 作为初学者,对递归编程表示很蒙逼,每次遇到需要递归的问题,心里就有一万头草泥马飞过~~~~~~(此处略去一万头草泥马) 在B站看数据结构与算法的视频时,视频中给了两个 ...
- 18/10/19 周五欢乐赛题解(c++版)
注意本题解并没有去追求最优解,只是用比较暴力的方法求解.D题听说要改说明不是位数30位,目前除了D题可能有问题之外其他代码已经全部正确. A.查找字串 用string BF(暴力求解即可) 代码 #i ...
- 33.bucket与metric核心概念讲解
主要知识点: bucket与metric核心慨念 一.核心慨念 1.bucket:一个数据分组 比如有下面几条数据: city name 北京 小李 北京 小王 上海 小张 上海 小丽 上海 小陈 ...
- 17.使用原生cross-fiels技术解决搜索弊端
主要知识点: 原生cross-fiels的用法 原生cross-fiels解决三个弊端 一.原生cross-fiels的用法 GET /forum/article/_search { ...
- Java基础学习总结(72)——提升 java 代码的运行效率
前言 代码 优化 ,一个很重要的课题.可能有些人觉得没用,一些细小的地方有什么好修改的,改与不改对于代码的运行效率有什么影响呢?这个问题我是这么考虑的,就像大海里面的鲸鱼一样,它吃一条小虾米有用吗?没 ...
- python实现字符串之间的映射
类似于凯撒密码一样的加密 # *-* coding=utf-8 *-* import string intab = string.lowercase outtab = 'qwertyuiopasdfg ...