package practice;

import edu.princeton.cs.algs4.*;

public class TestMain {
public static void main(String[] args) {
int[] a = new int[20];
for (int i = 0; i < a.length; i++) {
int temp = (int)(StdRandom.uniform(1, 10));
a[i] = temp;
} for (int i : a) {
System.out.print(i+" ");
}
System.out.println();
ToSort.sort3Way(a);
for (int i : a) {
System.out.print(i+" ");
}
}
} class ToSort{
private static int[] anx;
/*
* 我第一次写出来的快速排序,容易理解,但需要一倍的额外空间,也不快.....
*/
public static void mySort(int[] a) {
anx = new int[a.length];
myQuickSort(a, 0, a.length - 1);
}
public static void myQuickSort(int[] a,int lo,int hi) {
if (lo >= hi) return;
int m = lo;
int n = hi;
int mid = a[lo];
for (int i = lo + 1; i <= hi; i++) {
if (a[i] <= mid) anx[m++] = a[i];
else if (a[i] > mid) anx[n--] = a[i];
}
//此处往后m,n相等
anx[m] = mid;
for (int i = lo; i <= hi; i++) a[i] = anx[i];
myQuickSort(a, lo, m - 1);
myQuickSort(a, n + 1, hi);
}
/*
* 快速排序 时间复杂度O(NlgN)
*/
public static void sort(int[] a) {
quickSort(a, 0, a.length - 1);
}
public static void quickSort(int[] a,int lo,int hi) {
if (lo >= hi) return; //如果分到只剩一个元素,或没有元素,则返回
int n = partition(a, lo, hi); //将数组切分,取一个中值,分成比它小的一部分和比它大的一部分
quickSort(a, lo, n - 1); //将两部分分别快速排序
quickSort(a, n + 1, hi);
}
public static int partition(int[] a,int lo,int hi) {
int mid = a[lo]; //把第一个元素设为中值,先放在最左边不管
int m = lo;
int n = hi + 1;
while (true) {
while (a[++m] < mid) if(m == hi) break; //从左开始找出一个比mid大的元素
while (a[--n] > mid)/*if(n == lo) break; 这句没用,但可以让人更容易理解程序*/;//从右开始找出一个比mid小的元素
if (m >= n) break; //找完了
exch(a, m, n);
}
exch(a, n, lo); //把最左端中值和"比它小的值中最右端的数"换位置,它就到最中间了
return n;
}
/*
* 三向切分的快速排序,适用于有大量重复元素的数组
*/
public static void sort3Way(int[] a) {
quickSort(a, 0, a.length - 1);
}
public static void quickSort3Way(int[] a,int lo,int hi) {
if (lo >= hi) return;
int mid = a[lo];
int lt = lo + 1;
int gt = hi;
int i = lo + 1;
while (i <= gt) { //将比中值小的放在最左端,比中值大的放在最右端,和中值相等的放在中间
if (a[i] < mid) exch(a, lt++, i++); //换过来的值还是与中值相等的值,所以不用动
else if (a[i] > mid) exch(a, gt--, i); //换过来的值不知道是什么值,所以还要处理
else if (a[i] == mid) i++; //相等就过
}
exch(a, lo, lt - 1); //把最左端中值和"比它小的值中最右端的数"换位置
quickSort3Way(a, lo, lt - 2); //调用自己处理剩下的两部分
quickSort3Way(a, gt + 1, hi);
}
/*
* 交换a[i]与a[j]的值
*/
private static void exch(int[] a, int i, int j) {
int t = a[i];
a[i] = a[j];
a[j] = t;
}
}

快速排序示意图(图片来自《算法(第四版官网)》)

三向切分的快速排序示意图(图片来自《算法(第四版官网)》)

快速排序Java实现的更多相关文章

  1. 快速排序 Java实现的快速排序

    快速排序  Java实现的快速排序: package xc; import java.util.Arrays; import java.util.Random; /** * * @author dax ...

  2. 基本排序算法——快速排序java实现

    简单的快速排序算法,我竟然花费了如此多的时间来写作,好好学习. /** * */ package basic.sort; import java.util.Arrays; import java.ut ...

  3. 排序算法----快速排序java

    快速排序是对冒泡排序的一种改进,平均时间复杂度是O(nlogn) import java.util.Arrays; import java.util.Scanner; public class tes ...

  4. 快速排序 java详解

    1.快速排序简介: 快速排序由C. A. R. Hoare在1962年提出.它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此 ...

  5. ADV-297 快速排序 java

    问题描述 用递归来实现快速排序(quick sort)算法.快速排序算法的基本思路是:假设要对一个数组a进行排序,且a[0] = x.首先对数组中的元素进行调整,使x放在正确的位置上.同时,所有比x小 ...

  6. 快速排序-java

    排序-快速排序 基本思想: 将数据划分为两部分,左边的所有元素都小于右边的所有元素:然后,对左右两边进行快速排序. 划分方法: 选定一个参考点(中间元素),所有元素与之相比较,小的放左边,大的放右边. ...

  7. 数组排序-冒泡排序-选择排序-插入排序-希尔排序-快速排序-Java实现

    这五种排序算法难度依次增加. 冒泡排序: 第一次将数组相邻两个元素依次比较,然后将大的元素往后移,像冒泡一样,最终最大的元素被移到数组的最末尾. 第二次将数组的前n-1个元素取出,然后相邻两个元素依次 ...

  8. 排序算法之快速排序(java实现)

    package com.javaTest300; public class Test039 { public static void main(String[] args) {// 快速排序 int ...

  9. 快速排序java

    快速排序(Quicksort)是对冒泡排序的一种改进.它是先在数组中找到一个关键数,第一趟排序将比关键数小的放在它的左边,比关键数大的放在它的右边.当第一趟排序结束后,再依次递归将左边和右边的进行排序 ...

随机推荐

  1. VMware workstation批量创建虚拟机和自动化安装操作系统(一)

    一. 简述 作为从事IT行业运维工作的Linuxer,大多情况下需要在测试环境中部署业务系统并进行测试,在没有足够的计算存储网络条件下,使用虚拟机进行虚拟集群的创建和使用,是一种不错的学习和实践方式. ...

  2. Java 编程 订单、支付、退款、发货、退货等编号主动生成类

    订单.支付.退款.发货.退货等编号主动生成类 在商城网站中,订单编号的自动生成,ERP中各个单据的编号自动生成,都可以按照一下的方式来自动生成. 第一步:定义常量订单编号前缀.订单编号起始数.订单编号 ...

  3. C#生成无重复的随机数

    大一学期末的时候做课程设计时遇到过生成无重复随机数的问题,今天自己也写出来了: static int[] Create_Value() { Random ran = new Random(); //生 ...

  4. ddos攻击和cc攻击的区别和防护!!

    什么是DDoS攻击? DDoS攻击就是分布式的拒绝服务攻击,DDoS攻击手段是在传统的DoS攻击基础之上产生的一类攻击方式.单一的DoS攻击一般是采用一对一方式的,随着计算机与网络技术的发展,DoS攻 ...

  5. selenium + ChromeDriver

    Selenium是一个用于Web应用程序测试的工具.Selenium测试直接运行在浏览器中,就像真正的用户在操作一样.而对于爬虫来说,使用Selenium操控浏览器来爬取网上的数据那么肯定是爬虫中的杀 ...

  6. promise处理多个相互依赖的异步请求

    在项目中,经常会遇到多个相互依赖的异步请求.如有a,b,c三个ajax请求,b需要依赖a返回的数据,c又需要a和b请求返回的数据.如果采用请求嵌套请求的方式自然是不可取的.导致代码难以维护,如何请求很 ...

  7. 【转载】跟我一起学习VIM - vim插件

    目录 写在前面:Life Changing Editor 什么是VIM 为什么选VIM 为什么选其它 为什么犹豫选择它们 VIM >= SUM(现代编辑器) 如何学习VIM 一秒钟变记事本 VI ...

  8. 初识webview

    一.什么是webview   原生APP开发中有一个webview的组件(Android中是webview,iOS7以下有UIWebview,7以上有WKWebview),这个组件可以加载Html文件 ...

  9. Java范型

    泛型不用考虑对象的具体类型.优点在于,因为不用考虑对象的具体类型所以可以对一类对象执行一定的相同操作:缺点在于,因为没有考虑对象的具体类型所以就不能使用对象自带的接口函数.泛型的最佳用同是实现容器类. ...

  10. Markdown转HTML/pdf格式

    Markdown转HTML/pdf格式 通过_github自带_的更新博客的网页: https://github.com/YOUR_GITHUB_ACCOUNT/YOUR_GITHUB_ACCOUNT ...