原文:https://my.oschina.net/u/1382972/blog/169747

还可以参考:http://blog.csdn.net/stushan/article/details/51172296

快排算法的特点

  • 实用性强。

很多实际的项目中使用了快排算法。但通常对算法都进行了调整(tuning),比如Java.util.Arrays类中的sort函数就使用了快排算法,但使用了双参考值(Dual-Pivot Quicksort)等一些改进措施。由于快排算法为递归算法,可以用循环代替递归函数调用,改进性能。

  • 不需要额外的空间。

可以将数组中的数据直接交换位置实现排序,所以理论上不需要额外的空间。

时间复杂度

  • 平均情况:O(nlgn)
  • 最坏情况:O(n*n),发生在当数据已经是排序状态时

快排算法的基本原理

1、从数据中选取一个值a[i]作为参考
2、以a[i] 为参考,将数据分成2部分:P1、P2,P1中的数据全部≤a[i],P2中的数据全部>a[i],数据变为{{P1}{a[i]}{P2}}
3、将P1、P2重复上述步骤,直到各部分中只剩1个数据
4、数据完成升序排列

示例:

原始数据:{3,9,8,5,2,1,6}
第1步:选取第1个数据:3
第2步:将数据分成2部分,左边≤3,右边大于>3:{2,1} {3} {9,8,5,6}
第3步:将各部分重复以上步骤,直到每部分只剩1个数据:{2,1} => {1} {2}{9,8,5,6} => {8,5,6} {9}=> {5,6} {8} {9}=> {5} {6} {8} {9}
第4步:数据完成升序排列:{1} {2} {3} {5} {6} {8} {9}

程序中数据通常保存在数组中,以int类型的数组为例,可以将上面的步骤写成一个quickSort函数原型:

quickSort(int begin, int end) {
//begin为数组的第一个数据的索引值,end为数组的最后一个数据的索引值+1//如果只有1个数据或0个数据,则程序返回if( begin == end || begin == (end-1) ) return; int p = in[begin];//p为选择的参考数据,选择第一个数据int a = begin +1; //a作为2部分数据分界线的索引值int b = a;//b为待比较的数据的索引值for( ; b < end; b++) {//将数组中的各个数据依次与参考数据进行比较if( in[b] < p) { //如果该数据<参考数据则将其移动到左边if(a == b){a++; continue;} //如果该数据已经在左边则不动int temp = in[a];//将数据移动到左边in[a] = in[b];in[b] = temp;a++;//将分界线右移}}in[begin] = in[a-1];//讲参考值移动到2组数据中间in[a-1] = p;if( a-1 > begin){ // 如果左边有数据则将其重复上述步骤quickSort(begin, a);} if( end-1 > a ) {// 如果右边有数据则将其重复上述步骤quickSort(a, end);} return; // 如果无数据返回
}

使用泛型实现快排算法

下面设计一个QuickSort类,包含了静态函数sort(),可以对任意类型数组进行排序。如果为对象类型数组,则该对象类型必须实现Comparable接口,这样才能使用compareTo函数进行比较。

使用了最基本的快排算法,没有进行优化处理。

源代码如下:

import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Random;public class QuickSort {@SuppressWarnings("unchecked")//对上述快排函数原型修改,使其可以对任意对象类型数组进行排序。这个函数为内部使用,外部排序函数接口为sort(),sort函数要求对象必须实现Comparable接口,可以提供编译时类型检测,见后文。private static void quickSort(Object[] in,int begin, int end) {if( begin == end || begin == (end-1) ) return;Object p = in[begin];int a = begin +1;int b = a;for( ; b < end; b++) {//该对象类型数组必须实现Comparable接口,这样才能使用compareTo函数进行比较if( ((Comparable<Object>)in[b]).compareTo(p) < 0) {if(a == b){a++; continue;}Object temp = in[a];in[a] = in[b];in[b] = temp;a++;}}in[begin] = in[a-1];in[a-1] = p;if( a-1 > begin){quickSort(in,begin, a);} if( end-1 > a ) {quickSort(in,a, end);} return;}//使用泛型,对任意对象数组排序,该对象类型数组必须实现Comparable接口public static <T extends Comparable<? super T>> void sort(T[] input){quickSort(input,0,input.length);}//添加对List对象进行排序的功能,参考了Java中的Java.util.Collections类的sort()函数public static <T extends Comparable<? super T>> void sort(List<T> list){Object[] t = list.toArray();//将列表转换为数组quickSort(t,0,t.length); //对数组进行排序//数组排序完成后再写回到列表中ListIterator<T> i = list.listIterator();for (int j=0; j<t.length; j++) {i.next();i.set((T)t[j]);}}//由于Java中原始数据类型(int、double、byte等)无法使用泛型,所以只能使用函数重载机制实现对这些原始类型数组(int[]、double[]、byte[]等)的排序。这里为了共用同一个排序函数,利用原始类型的(AutoBoxing,UnBoxing)机制将其封装为对应对象类型,组成新的对象数组,排序后再解封装,这样的缺点是需要额外的转换步骤、额外的空间保存封装后的数组。另一种方式是将排序代码复制到各个重载函数中,官方API中的Java.util.Arrays这个类中的sort()函数就是使用这种方法,可以从Arrays类的源代码看出。public static void sort(int[] input){Integer[] t = new Integer[input.length];for(int i = 0; i < input.length; i++){t[i] = input[i];//封装}quickSort(t,0,t.length);//排序for(int i = 0; i < input.length; i++){input[i] = t[i];//解封装}}//double[]数组的重载函数public static void sort(double[] input){Double[] t = new Double[input.length];for(int i = 0; i < input.length; i++){t[i] = input[i];}quickSort(t,0,t.length);for(int i = 0; i < input.length; i++){input[i] = t[i];}}//byte[]数组的重载函数public static void sort(byte[] input){Byte[] t = new Byte[input.length];for(int i = 0; i < input.length; i++){t[i] = input[i];}quickSort(t,0,t.length);for(int i = 0; i < input.length; i++){input[i] = t[i];}}//short[]数组的重载函数public static void sort(short[] input){Short[] t = new Short[input.length];for(int i = 0; i < input.length; i++){t[i] = input[i];}quickSort(t,0,t.length);for(int i = 0; i < input.length; i++){input[i] = t[i];}}//char[]数组的重载函数public static void sort(char[] input){Character[] t = new Character[input.length];for(int i = 0; i < input.length; i++){t[i] = input[i];}quickSort(t,0,t.length);for(int i = 0; i < input.length; i++){input[i] = t[i];}}//float[]数组的重载函数public static void sort(float[] input){Float[] t = new Float[input.length];for(int i = 0; i < input.length; i++){t[i] = input[i];}quickSort(t,0,t.length);for(int i = 0; i < input.length; i++){input[i] = t[i];}}//测试用的main函数public static void main(String[] args) {//生产一个随机数组成的int[]数组,用来测试int LEN = 10;int[] input = new int[LEN];Random r = new Random();System.out.print("int[] before sorting: ");for(int i = 0; i < input.length; i++) {input[i] = r.nextInt(10*LEN);System.out.print(input[i] + " ");}System.out.println();System.out.print("int[] after sorting: ");sort(input);for(int i : input) {System.out.print(i + " ");} System.out.println();//生成一个字符串数组,用来测试String[] s = new String[]{"b","a","e","d","f","c"};System.out.print("String[] before sorting: ");for(int i = 0; i < s.length; i++) {System.out.print(s[i] + " ");}System.out.println();System.out.print("String[] after sorting: ");sort(s);for(int i = 0; i < s.length; i++) {System.out.print(s[i] + " ");}System.out.println();//生成一个字符串列表,用来测试List<String> l = new LinkedList<String>();s = new String[]{"b","a","e","d","f","c"};System.out.print("LinkedList<String> before sorting: ");for (int j=0; j<s.length; j++) {l.add(s[j]);System.out.print(s[j] + " ");}System.out.println();sort(l);System.out.print("LinkedList<String> after sorting: ");for (String ts : l) {System.out.print(ts + " ");}System.out.println();}
}

运行main函数测试,从输出可以看出QuickSort类工作正常:

int[] before sorting: 65 48 92 26 3 8 59 21 16 45
int[] after sorting: 3 8 16 21 26 45 48 59 65 92
String[] before sorting: b a e d f c
String[] after sorting: a b c d e f
LinkedList<String> before sorting: b a e d f c
LinkedList<String> after sorting: a b c d e f

使用Java泛型实现快速排序(快排,Quicksort)相关推荐

  1. 快速排序(快排)--->注释超详细

    基本思想:         1.先选取一个基准值(一般选取数组第一个元素).         2.以第一步选取的基准值为标准,然后从最后一个数值开始一步步向前走将数字与基准值进行比较,如果该值大于基准 ...

  2. c语言快排过程,快速排序(快排)C语言实现

    快速排序 快速排序由C. A. R. Hoare在1962年提出.它的基本思想是:经过一趟排序将要排序的数据分割成独立的两部分,其中一部分的全部数据都比另一部分的全部数据都要小,而后再按此方法对这两部 ...

  3. 【数据结构与算法】八大排序(中)快速排序 快排居然还能这么优化?快排的非递归该如何写?

  4. 快排Java代码实现(Quick Sort)

    1.  快排算法思路 基本思想:通过一趟快速排序将待排数组分割成独立的两份部分; 其中一部分数组的值均比另一部分数组的值小,则可分别对着两部分数组继续进行排序,以达到整个序列有序. 快排的平均时间复杂 ...

  5. java jdk实现快速排序_Java实现快速排序过程分析

    快速排序过程 没有既不浪费空间又可以快一点的排序算法呢?那就是"快速排序"!光听这个名字是不是就觉得很高端呢. 假设我们现在对"52 39 67 95 70 8 25 5 ...

  6. java数据结构之快速排序

    排序算法是java数据结构的基础,也是程序员必备的基础算法之一,个人认为,了解并掌握排序算法的思想比起单纯用代码实现功能更有意义,毕竟创造这套算法的思想才是最高的智慧嘛,下面就来说说关于排序算法中的比 ...

  7. 堆排序和快排与归并排序

    目录 快速排序 算法思想 算法的优化 代码实现 归并排序 算法思想 算法优化 代码实现 堆排序 算法思想 代码实现 本文主要介绍了三个排序算法的思想原理和Java代码实现 快速排序 快排序的一个优点是 ...

  8. 非递归的方法写快排java_快排的最差情况以及快排平均复杂度的计算

    最近突然讨论了这两个问题,有点忘记了,记录了一下网上的比较好的说法,参见Reference 快排的相关知识请参考排序总结 快排的最差情况以及如何避免 首先,快排的最差情况什么时候发生? 1. 已排序 ...

  9. 12 | 排序(下):如何用快排思想在O(n)内查找第K大元素?

    算法对比: 算法 时间复杂度 适合场景 冒泡排序.插入排序.选择排序 O(n2) 小规模数据 归并排序.快速排序 O(nlogn) 大规模数据 归并排序和快速排序都用到了分治思想,非常巧妙.我们可以借 ...

最新文章

  1. [leetcode] Bulb Switcher
  2. C++将数字A转换为数字B所需的翻转次数算法实现(附完整源码)
  3. 修改 IIS 队列长度
  4. ssm read time out的原因_自检轮胎暗漏原因_什么是自检轮胎暗漏原因
  5. 用C语言编写顺序存储的线性表(含代码实现)
  6. 启动mysql时显示:/tmp/mysql.sock 不存在的解决方法
  7. 如何在VS2013中隐藏引用计数?
  8. 数据结构和算法笔记:基数排序
  9. web文件操作常见安全漏洞(目录、文件名检测漏洞)
  10. VOA 2009.11.19-教育报道-美国大学创入学记录新高
  11. p6spy监测mysql_JDBC数据库访问操作的动态监测 之 p6spy
  12. 电视制式以及伴音载频制式详解
  13. python分号_python分号_python 分号_python加分号 - 云+社区 - 腾讯云
  14. 别跑!JAVA!-----------一篇关于JAVA的博客
  15. 需求驱动还是技术驱动,大跃进的聊天机器人在开着一辆往历史倒退的车
  16. Linux之安装Nginx(安装包方式)
  17. django:信号机制
  18. 【白兔兔】TiKZ画浮动汇率制度下的财政政策图
  19. 【渝粤教育】电大中专市场营销管理_1作业 题库
  20. 艾宾浩斯遗忘曲线PHP,【干货】~~~艾宾浩斯遗忘曲线~~~

热门文章

  1. 什么是机器人的五点校正法_样品定量检测怎样选择内标法和外标法!
  2. 红帽linux怎么更新源,redhat Linux配置yum更新源
  3. axure 导入元件库显示不出白框_AXURE免费元件库分享-web
  4. java 反射 工厂_JAVA反射机制、工厂模式与SPRING IOC
  5. mysql 随机选择数据_从MySQL随机选取数据
  6. 2012级计算机应用基础,2012年计算机应用基础
  7. php new redis错误,解决PHP Redis扩展无法加载的问题(zend_new_interned_string in Unknown on line 0)...
  8. 扔掉 Postman,Apifox 才是 YYDS!
  9. 从微服务架构的现状和未来看学习路径
  10. 建议被降级降薪员工主动辞职?网友炸了!