快速排序由于排序效率在同为O(N*logN)的几种排序方法中效率较高,因此经常被采用,再加上快速排序思想----分治法也确实实用,因此很多软件公司的笔试面试,包括像腾讯,微软等知名IT公司都喜欢考这个,还有大大小的程序方面的考试如软考,考研中也常常出现快速排序的身影。
总的说来,要直接默写出快速排序还是有一定难度的,因为本人就自己的理解对快速排序作了下白话解释,希望对大家理解有帮助,达到快速排序,快速搞定。
快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序。它采用了一种分治的策略,通常称其为分治法(Divide-and-ConquerMethod)。
该方法的基本思想是:
1.先从数列中取出一个数作为基准数。
2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。
3.再对左右区间重复第二步,直到各区间只有一个数。
通过一躺排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一不部分的所有数据都要小,然后再按次方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
下面我们看一个具体的例子 , 它的排序流程如下 :
1. 49 38 65 97 76 13 27 49] //初始关键字
2. [27 38 13] 49 [76 97 65 49] //第1次划分完成之后,对应递归树第2层
3. [13] 27 [38] 49 [49 65] 76 [97] //对上一层各无序区划分完成后,对应递归树第3层
4. 13 27 38 49 49 [65] 76 97 //对上一层各无序区划分完成后,对应递归树第4层
5. 13 27 38 49 49 65 76 97 //最后的排序结果
按照上述流程,我们可以得出下面的算法代码 :
/**
* @Title: QuitSort.java
* @Package
* @Description: 快速排序算法
* 算法思想:
* 该方法的基本思想是:
1.先从数列中取出一个数作为基准数。
2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。
3.再对左右区间重复第二步,直到各区间只有一个数。
* 首先选定枢轴,一般设置low所对应的元素位置为枢轴,如图选定的枢轴为26。
在高位指针始终不小于低位指针的前提下:
高位指针开始判断其数值是否比枢轴值大,如果符合,高位指针减1,继续寻找。直到找到枢轴值大于高位指针指向的数值,
然后把该值赋给此时低位所在位置;
低位指针开始判断其数值是否比枢轴值小,如果符合,低位指针加1,继续寻找。直到找到枢轴数值小于低位指针指向的数值,
然后将该值赋给此时高位指针所指位置。
如此反复,直到低位与高位指针重合,此时,再将当前的枢轴值赋给低位指针所指的值。这样就完成了一次排序。
此时枢轴值就到了其最终位置上,然后继续对以枢轴为轴的两部分进行排序。
* @author Mr.Simple bboyfeiyu@gmail.com
* @date May 2, 2013 4:29:09 PM
* @version V1.0
*/
public class QuickSort<T> {
/**
*
* @Title: quickSort
* @Description: 快速排序,对数组arr进行快速排序
* @param arr 待排序的数组
* @param low 低位
* @param high 高位
* @throws
*/
public static void quickSort(int[] arr, int low, int high){
if( low < high ){
// 枢轴位置
int povitePosition = adjust(arr, low, high);
display(arr) ;
// 左边较小的排序
quickSort( arr , low , povitePosition - 1);
// 右边较大的排序
quickSort( arr , povitePosition + 1 , high );
}
}
/**
*
* @Title: adjust
* @Description: 调整数组的枢轴位置
* @param arr int[] arr = {26, 53, 8, 15, 13, 90, 11, 32};
* @param low
* @param high
* @return
* @return int
* @throws
*/
private static int adjust(int[] arr, int low, int high){
// 选定Low位置的数值为枢轴
int pivoteKey = arr[low];
// 进行排序
while( low < high ){
// pivoteKey小于arr[high]的时候,继续往下寻找 high++
while( (low < high) && compare(pivoteKey, arr[high]) ){
high--;
}
// 高位的数值小于pivoteKey,则与低位交换数据
arr[low] = arr[high];
// 当pivoteKey比arr[low]大的时候,继续寻找low++
while( (low < high) && !compare(pivoteKey, arr[low])){
low++;
}
// 当pivoteKey小于arr[low]时,交换数据
arr[high] = arr[low];
}
arr[low] = pivoteKey;
return low ;
}
/**
*
* @Title: compare
* @Description: pivoteKey小于high
* @param pivoteKey 枢轴数值
* @param value 要数组中要对比的数值
* @return boolean
* @throws
*/
private static boolean compare(int pivoteKey, int value){
return pivoteKey < value ;
}
/**
*
* @Title: display
* @Description: 打印数组序列
* @param arr
* @return void
* @throws
*/
private static void display(int[] arr){
for(int i : arr){
System.out.print(i + " ") ;
}
System.out.println("\n") ;
}
/**
*
* @Title: main
* @Description: 快速排序
* @param args
* @return void
* @throws
*/
public static void main(String[] args){
int[] arr = {26, 53, 8, 15, 13, 90, 11, 32};
QuickSort.quickSort(arr, 0, arr.length - 1) ;
System.out.println("after quick sort : ") ;
display(arr) ;
}
}
参考: http://www.cnblogs.com/morewindows/archive/2011/08/13/2137415.html