快速排序及三向切分快排——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):返回大于或等于参数的最 ...
随机推荐
- RTL Compiler之Example
Synthesis = Translation + Logic Optimization + Mapping Step 1 Source files 1) make directory mkdir ...
- Android中Webview使用经验总结
很早前就喜欢在Android中使用Webview组件结合JS来做应用,总结了一些不错的小经验,在这里持续更新,自己备忘,也希望给其他需要的同学一些参考- 1.添加权限 要用Webview,确认你在** ...
- 求n!(高精度问题)
#include <iostream> #include <stdio.h> #define MAX 10000 using namespace std; void Mul(i ...
- Scrapy实战:爬取http://quotes.toscrape.com网站数据
需要学习的地方: 1.Scrapy框架流程梳理,各文件的用途等 2.在Scrapy框架中使用MongoDB数据库存储数据 3.提取下一页链接,回调自身函数再次获取数据 重点:从当前页获取下一页的链接, ...
- R 安装car包失败
在RStudio里安装car包的时候报错 /usr/bin/ld: cannot find -llapack /usr/bin/ld: cannot find -lblas make: *** [qu ...
- odoo widget 标签介绍
widget="statusbar" 头部状态条标签 widget="email" 电子邮件地址标签 widget="selection" ...
- 关于框架搭建-web
最近一直在学习前端相关的东西,在学了一堆基础可以以及动手在某个前端框架上写了一些东西之后,我想尝试着开始自己搭建一个框架.不知道时间需要多久,但会持续更新.小菜鸟的成长记录. ------------ ...
- hadoop在线退役datanode
退役dn2echo "dn2" >>excludes echo "dn2" >>yarn-excludes sh refresh-nam ...
- 清北学堂模拟赛d2t5 吃东西(eat)
题目描述一个神秘的村庄里有4家美食店.这四家店分别有A,B,C,D种不同的美食.LYK想在每一家店都吃其中一种美食.每种美食需要吃的时间可能是不一样的.现在给定第1家店A种不同的美食所需要吃的时间a1 ...
- RPC框架分析
RPC框架分析 常用的框架 .net(WCF) .net中分布式框架集大成者,提供多种通信方式,多种安全策略的调用(配置繁琐). java 1.RMI JDK原生(严格的说来算不上框架). 2.Du ...