快速排序也是用归并方法实现的一个“分而治之”的排序算法,它的魅力之处在于它能在每次partition(排序算法的核心所在)都能为一个数组元素确定其排序最终正确位置(一次就定位准,下次循环就不考虑这个元素了)。

  快速排序的partition操作按以下逻辑进行,假定本次排序的数组为arr:

1) 选择一个元素(为了简单起见,就选择本次partition的第一个元素,即arr[0])作为基准元素,接下来的步骤会为其确定排序完成后最终的位置;

2) 1)  接下来需要遍历[1…n-1]对应的数组元素以帮助找到arr[0]值(以v替代)对应的位置,定义i为当前访问数组的索引,lt为值小于v的最大索引,gt为值大于v的最小索引,那么在遍历过程中,如果发现i指向的值与v相等,则将i值加1,继续下一次比较;如果i指向的值比v小,则将i和lt对应的元素进行交换,然后分别将两个索引加1;如果i指向的值比v大,则将i与gt对应的元素进行交换,然后i自增,gt自减。循环遍历完成(i > gt时结束)之后可以保证[0…lt-1]对应的值都是比v小的,[lt..gt]之间的值都是与v相等的,[gt+1…n-1]对应的值都是比v大的。

3) 分别对[0…lt-1]和[gt+1…n-1]两个子数组进行排序,如此递归,直至子子子数组的长度为0。

  下面举个partition的具体实例:

初始(i = 1, lt = 0, gt = 8):

       [41, 59, 43, 26, 63, 30, 29, 26, 42](需要确定位置的为0th[41])

第一趟(i = 1, lt = 0, gt = 8):

       [41, 42, 43, 26, 63, 30, 29, 26, 59](1st[59] > 41,1st[59]<->8th[42],gt--)

第二趟(i = 1, lt = 0, gt = 7):

       [41, 26, 43, 26, 63, 30, 29, 42, 59](1st[42] > 41,1st[42]<->7th[26],gt--)

第三趟(i = 1, lt = 0, gt = 6):

       [26, 41, 43, 26, 63, 30, 29, 42, 59](1st[26] < 41, 1st[26]<->0st[41],i++, lt++)

第四趟(i = 2, lt = 1, gt = 6):

       [26, 41, 29, 26, 63, 30, 43, 42, 59](2nd[43] > 41,2nd[43]<->6th[29],gt--)

第五趟(i = 2, lt = 1, gt = 5):

       [26, 29, 41, 26, 63, 30, 43, 42, 59](2nd[29] < 41, 2nd[29]<->1st[41],i++,lt++)

第六趟(i = 3, lt = 2, gt = 5):    

       [26, 29, 26, 41, 63, 30, 43, 42, 59](3rd[26] < 41,3rd[26]<->2nd[41],i++,lt++)

第七趟(i = 4, lt = 3, gt = 5):

       [26, 29, 26, 41, 30, 63, 43, 42, 59] (4th[63] > 41,4th[63]<->5th[30],gt--)

第八趟(i = 4, lt = 3, gt = 4):    

       [26, 29, 26, 30, 41, 63, 43, 42, 59](4th[30] < 41,4th[30]<->3rd[41],i++,lt++)

可以看出,在一次partition之后,以41为分割线,41左侧皆为比它小的元素,41右侧皆为比它大或相等的元素(当然这个实例比较特殊,没有出现和41相等的元素)。快速排序顾名思义就是排序速度非常快,后面我会放在我机器上跑各个排序方法的时间对比图。值得一提的是JDK中在Arrays工具内中内置的sort方法就是接合插入排序和三路快速排序实现的,有兴趣的同学可以看看JDK的源码。

快速排序使用分治法策略来把一个序列分为两个子序列。

把整个序列看做一个数组,把第零个位置看做中轴,和最后一个比,如果比它小交换,比它大不做任何处理;交换了以后再和小的那端比,比它小不交换,比他大交换。这样循环往复,一趟排序完成,左边就是比中轴小的,右边就是比中轴大的,然后再用分治法,分别对这两个独立的数组进行排序。

实现代码:

/**
* 快速排序<br/>
* <ul>
* <li>从数列中挑出一个元素,称为“基准”</li>
* <li>重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分割之后,
* 该基准是它的最后位置。这个称为分割(partition)操作。</li>
* <li>递归地把小于基准值元素的子数列和大于基准值元素的子数列排序。</li>
* </ul>
*
* @param numbers
* @param start
* @param end
*/
public static void quickSort(int[] numbers, int start, int end) {
if (start < end) {
int base = numbers[start]; // 选定的基准值(第一个数值作为基准值)
int temp; // 记录临时中间值
int i = start, j = end;
do {
while ((numbers[i] < base) && (i < end))
i++;
while ((numbers[j] > base) && (j > start))
j--;
if (i <= j) {
temp = numbers[i];
numbers[i] = numbers[j];
numbers[j] = temp;
i++;
j--;
}
} while (i <= j);
if (start < j)
quickSort(numbers, start, j);
if (end > i)
quickSort(numbers, i, end);
}
}

Java算法-快速排序的更多相关文章

  1. java算法----排序----(4)快速排序

    package log; public class Test4 { /** * java算法---快速排序 * * @param args */ public static void main(Str ...

  2. JAVA算法系列 快速排序

    java算法系列之排序 手写快排 首先说一下什么是快排,比冒泡效率要高,快排的基本思路是首先找到一个基准元素,比如数组中最左边的那个位置,作为基准元素key,之后在最左边和最右边设立两个哨兵,i 和 ...

  3. 《Java算法》排序算法-快速排序

    排序算法-快速排序: /** * 给定一个数组:按照从小到大排序. * 思路: * 1. 获取第一个数放入临时变量data,将大于data的数放右边,小于data的数放在左边. * 2. data左边 ...

  4. 数据结构和算法(Golang实现)(25)排序算法-快速排序

    快速排序 快速排序是一种分治策略的排序算法,是由英国计算机科学家Tony Hoare发明的, 该算法被发布在1961年的Communications of the ACM 国际计算机学会月刊. 注:A ...

  5. JAVA算法系列 冒泡排序

    java算法系列之排序 手写冒泡 冒泡算是最基础的一个排序算法,简单的可以理解为,每一趟都拿i与i+1进行比较,两个for循环,时间复杂度为 O(n^2),同时本例与选择排序进行了比较,选择排序又叫直 ...

  6. java算法 蓝桥杯 乘法运算

    问题描述 编制一个乘法运算的程序. 从键盘读入2个100以内的正整数,进行乘法运算并以竖式输出. 输入格式 输入只有一行,是两个用空格隔开的数字,均在1~99之间(含1和99). 输出格式 输出为4行 ...

  7. java算法 蓝桥杯 扶老奶奶街

    一共有5个红领巾,编号分别为A.B.C.D.E,老奶奶被他们其中一个扶过了马路. 五个红领巾各自说话: A :我和E都没有扶老奶奶 B :老奶奶是被C和E其中一个扶过大街的 C :老奶奶是被我和D其中 ...

  8. java算法 蓝桥杯 高精度加法

    问题描述 在C/C++语言中,整型所能表示的范围一般为-231到231(大约21亿),即使long long型,一般也只能表示到-263到263.要想计算更加规模的数,就要用软件来扩展了,比如用数组或 ...

  9. java算法 蓝桥杯 格子位置

    问题描述 输入三个自然数N,i,j (1<=i<=N,1<=j<=N),输出在一个N*N格的棋盘中,与格子(i,j)同行.同列.同一对角线的所有格子的位置. 输入格式 输入共三 ...

随机推荐

  1. codeforces 709D D. Recover the String(构造)

    题目链接: D. Recover the String time limit per test 1 second memory limit per test 256 megabytes input s ...

  2. POJ 1269 Intersecting Lines【判断直线相交】

    题意:给两条直线,判断相交,重合或者平行 思路:判断重合可以用叉积,平行用斜率,其他情况即为相交. 求交点: 这里也用到叉积的原理.假设交点为p0(x0,y0).则有: (p1-p0)X(p2-p0) ...

  3. POJ 1061 青蛙的约会【扩展欧几里德】

    设跳的次数为t 根据题意可得以下公式:(x+mt)%L=(y+nt)%L 变形得 (x+mt)-(y+nt)=kL (n-m)t+kL=x-y 令a=(n-m),b=L,c=x-y 得 at+bk=c ...

  4. nginx 一二事(3) - 反向代理以及负载均衡

    先来说说正向代理 就是普通的代理,记得高中年代偷跑去网吧是要办卡的 题外话: 就是这货...相信很多80同龄人都有吧...    回到正题,那正向代理就不让你直接访问网络,而需要登录一下网吧的某个系统 ...

  5. web安全测试工具的局限性

    讨论安全漏洞的原理,谈谈工具的局限. 先说下扫描工具的原理: 扫描工具可以看做由两部分组成:爬虫+校验机构.爬虫的作用是搜集整个被采集对象的链接,然后校验机构对这些链接逐一进行验证. 说扫描工具的局限 ...

  6. 如何修复AppScan漏洞

    [AppScan]修复漏洞一:启用不安全的HTTP方法 (中) 漏洞背景:      “启用了不安全的 HTTP 方法”属于“中”危漏洞.漏洞描述是:根据APPSCAN的报告,APPSCAN通过OPT ...

  7. javascript中的array对象属性及方法

    Array 对象 Array 对象用于在单个的变量中存储多个值. 创建 Array 对象的语法: new Array(); new Array(size); new Array(element0, e ...

  8. C语言 结构体中的成员域偏移量

    //C语言中结构体中的成员域偏移量 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> # ...

  9. 如何解决机器重启后MySql服务跑不起来了1067,附解决过程

    今个一位同事的mysql跑不起来了,之前还好好的,问我怎么恢复,我没在她出问题的机器上弄,在自己机器上试的,最终在CTO的指导下解决了,现记录于此. 1,首先把她的mysql安装文件夹.数据结构文件. ...

  10. Sql语句里的递归查询

    Sql语句里的递归查询 SqlServer2005和Oracle 两个版本 以前使用Oracle,觉得它的递归查询很好用,就研究了一下SqlServer,发现它也支持在Sql里递归查询举例说明:Sql ...