快速排序及其Java实现(以升序为例)
来源:互联网 发布:淘宝关键词哪里设置 编辑:程序博客网 时间:2024/06/13 22:25
与合并排序一样,快速排序也是基于分治模式的。下面是对数组A[p…r]排序的分治过程的三个步骤:
分解:数组A[p…r]被划分为两个(可能空)的子数组A[p…q-1]和A[q+1…r],其中A[p…q-1]中的元素均小于A[q],A[q+1…r]中的元素均大于A[q]。
解决:通过递归调用快速排序,对子数组A[p…q-1]和A[q+1…r]进行就地排序
合并:因为两个子数组是就地排序的,将它们合并不需要操作。
简述一下快速排序的基本思想:在数组中选一个数作为轴中值(pivot),通过不断地比较将这个轴中值放在正确的位置上(左边的数比它小,右边的数比它大)。然后再递归地在左边的子序列和右边的子序列进行同样的操作,直到子序列的长度为1.
快速排序的思想很简单,但是通过上面的介绍可以看到两个问题:
1.轴中值(pivot)怎么选?
轴中值可以随便选。
在这篇博客里介绍两种选法:a)每次都选序列最后的元素 b)随机选择
2.怎么通过比较把轴中值放在合适的位置上?
先给这个操作取个名字:PARTITION,我们要向他传递三个参数:A,p,r.
A是数组名,p是子序列第一个元素,r是子序列最后一个元素。
在各种PATITION操作的讲解中,代码是最简单直白的,下面给出PATITION操作的Java代码:
static int partition(int[] a,int p,int r) { int temp = a[r]; int i = p-1; int swap = 0; //用于交换的临时变量 for(int j = p;j < r;j++) { if(a[j]<temp) { i++; swap = a[i]; //交换,这里的交换用临时变量,因为可能要和自己做交换 a[i] = a[j]; a[j] = swap; } } swap = a[i+1]; //交换 a[i+1] = a[r]; a[r] =swap; return i+1;}
下面以序列[13,19,9,5,12,8,7,4,21,2,6,11]为例展示PARTITON操作(轴中值取最后一个元素):
快速排序就是不断在子序列中做PARTITION操作,下面给出QuickSort的全部Java代码:
package ex;import java.util.Arrays;public class Sort { public static void main(String args[]) { int []a = new int[] {13,19,9,5,12,8,7,4,21,2,6,11}; quickSort(a,0,a.length-1); System.out.println(Arrays.toString(a)); } static int partition(int[] a,int p,int r) { int temp = a[r]; int i = p-1; int swap = 0; for(int j = p;j < r;j++) { if(a[j]<temp) { i++; swap = a[i]; //交换,这里的交换增加一个临时变量,因为可能要和自己做交换 a[i] = a[j]; a[j] = swap; } } swap = a[i+1]; //交换 a[i+1] = a[r]; a[r] =swap; return i+1; } static void quickSort(int[] a,int p,int r) { if(p>=r) //递归的边界条件 return; else { int q = partition(a,p,r); quickSort(a,p,q-1); quickSort(a,q+1,r); } }} //输出结果://[2, 4, 5, 6, 7, 8, 9, 11, 12, 13, 19, 21]
在上面代码的基础上给出快速排序的随机化版本:
package ex;import java.util.Arrays;import java.util.Random;public class Sort { public static void main(String args[]) { int []a = new int[] {13,19,9,5,12,8,7,4,21,2,6,11}; //quickSort(a,0,a.length-1); randomizedQuickSort(a,0,a.length-1); System.out.println(Arrays.toString(a)); } static int partition(int[] a,int p,int r) { int temp = a[r]; int i = p-1; int swap = 0; for(int j = p;j < r;j++) { if(a[j]<temp) { i++; swap = a[i]; //交换,这里的交换用临时变量,因为可能要和自己做交换 a[i] = a[j]; a[j] = swap; } } swap = a[i+1]; //交换 a[i+1] = a[r]; a[r] =swap; return i+1; } static int randomizedPartition(int[] a,int p,int r) { Random rd = new Random(); int i = rd.nextInt(r-p+1) + p; //生成[r,p]之间的随机整数 int swap = a[i]; a[i] = a[r]; //交换 a[r] = swap; return partition(a,p,r); } static void randomizedQuickSort(int[] a,int p,int r) { if(p>=r) //递归的边界条件 return; else { int q = randomizedPartition(a,p,r); randomizedQuickSort(a,p,q-1); randomizedQuickSort(a,q+1,r); } }} //输出结果://[2, 4, 5, 6, 7, 8, 9, 11, 12, 13, 19, 21]
最后,再给出另一种版本的快速排序,它用循环取代了一部分递归,一定程度上提升了算法性能:
package ex;import java.util.Arrays;public class Sort { public static void main(String args[]) { int []a = new int[] {13,19,9,5,12,8,7,4,21,2,6,11}; improvedQuickSort(a,0,a.length-1); System.out.println(Arrays.toString(a)); } static int partition(int[] a,int p,int r) { int temp = a[r]; int i = p-1; int swap = 0; for(int j = p;j < r;j++) { if(a[j]<temp) { i++; swap = a[i]; //交换,这里的交换用临时变量,因为可能要和自己做交换 a[i] = a[j]; a[j] = swap; } } swap = a[i+1]; //交换 a[i+1] = a[r]; a[r] =swap; return i+1; } static void improvedQuickSort(int[] a,int p,int r) { while(p<r) { int q = partition(a,p,r); improvedQuickSort(a,p,q-1); //先对左子序列进行QuickSort p = q + 1; //再对右子序列进行同样的操作 } }} //输出结果://[2, 4, 5, 6, 7, 8, 9, 11, 12, 13, 19, 21]//在原来的快速排序中包含两个对自身的递归调用,这边只需要一个
如有错误,欢迎指正
- 快速排序及其Java实现(以升序为例)
- 堆排序算法及其Java实现(以大根堆为例)
- 快速排序:升序+降序----java实现
- 快速排序及其JAVA实现
- 快速排序及其java实现代码
- 查找两个排序数组的中间值--以升序数组为例
- 快速排序1 升序
- 快速排序(升序)
- 快速排序的基本思想及其java的实现
- 学习笔记----快速排序的java实现及其改良
- 快速排序及其变种 Java
- 快速排序-以高位为标志
- 快速排序(以中间为基准)
- 大根堆排序结果为升序
- 堆排序--采用快速排序(利用大堆实现升序,小堆实现降序)
- 【排序】05.快速排序(升序)
- java实现快速排序
- 快速排序Java实现
- react基础
- CentOS下安装python3
- Maven安装及使用
- HDU 5981 Guess the number
- 开源软件和开源协定
- 快速排序及其Java实现(以升序为例)
- codeforce 416 E floyd
- do...while(0)在宏定义中的巧妙用法
- Understanding the JVM(一)运行时数据区域
- Linux 学习
- 51nod 1423 最大“二货”【单调栈】
- 欢迎使用CSDN-markdown编辑器
- 又是一年忧桑季
- 550 Permission denied