快速排序的基本思想:首先将待排序记录序列中的所有记录作为当前待排序区域,从中任选取一个记录(通常可选取第一个记录),以它为关键字作为枢轴,凡是其关键字小于枢轴的记录均移动到该关键字之前,反之移动到该记录之后,这一趟排序后,记录的无序序列R[s..t]将分割成两部分,R[s..i-1]和R[i+1..t],且R[j].key<=R[i].key(s<=j<=i-1,R[i].key为枢轴,i+1<=k<=t)。
快速排序的实例:
一趟排序的过程
初始关键字序列: [51] 33 62 96 87 17 28 51
R[0]=[51] i↑(枢轴) ↑j
J向前扫描 i↑ ↑j
第一次交换之后: 28 33 62 96 87 17 [51] 51
i↑ ↑j
I向后扫描 i↑ ↑j
第二次交换之后: 28 33 [51] 96 87 17 62 51
i↑ ↑j
J向前扫描 i↑ ↑j
第三次交换之后: 28 33 17 96 87 [51] 62 51
I向后扫描 i↑ ↑j
第四次交换之后: 28 33 17 [51] 87 96 62 51
J向前扫描 i↑ ↑j
完成一趟排序: 28 33 17 [51] 87 96 62 51
快速排序全过程
初始关键字序列: [51] 33 62 96 87 17 28 51
一趟排序之后: [28 33 17] 51 [87 96 62 51]
分别进行快速排序: [17] 28 [33] 51 [51 62] 87 [96]
51 [62]
有序序列: 17 28 33 51 51 62 87 96
快速排序的Java算法:
public class Test2 {
/**
* @param args
* 快速排序
*
*/
public static void main(String[] args) {
// TODO Auto-generatedmethod stub
//定义一维数组
int[] R = {132,24,4,436,547,65,87,8,6,9,780,7,325,57,54,46,35,3,42,4};
//掉用quickSort方法,对一维数组排序,初始化low为0,最大值
quickSort(R, 0, R.length - 1);
//用for循环输出排序好的数组
for(int i = 0; i < R.length; i++) {
System.out.print(R[i] + " ");
}
}
//快速排序
//定义quickSort方法
static void quickSort(int R[], int low, int height) {
//对记录R[low...height]进行快速排序
if(low < height) {
int result = partition(R, low,height);
quickSort(R, low, result -1);
quickSort(R, result + 1,height);
}
}
//定义partition方法
static int partition(int R[], int low, int height) {
//交换记录子序列 R[low...height]的记录,使轴记录交换到正确的位置,并返回其所在的位置
int key = R[low]; //使用key存放枢轴记录的关键字
while(low < height) {
//从表的两端交替向中间扫描
while(low < height && R[height] >=key) {
height--;
}
R[low] = R[height]; //将比轴小的记录移到低端
while(low < height && R[low] <= key){
low++;
}
R[height] = R[low]; //将比轴大的记录移到高端
}
R[low] = key; //轴记录到位
return low; //返回轴记录位置
}
}
快速排序所需的平均时间复杂度为O(n log n)。就平均时间而言,快速排序是目前被认为最好的内部排序方法。但是,若待排记录的初始状态为关键字有序,快速排序将锐化成起泡排序,其时间复杂度为O(n2)。也就是说,一次划分后枢轴两侧的记录数量越接近,排序速度越快,待排序记录越有序,排序速度越慢。为避免排序后记录集中在枢轴一侧的情况,需要在进行快速排序之前,进行”预处理”。这里要说的是随机化快速排序。
随机化快速排序:在待排序序列中随机确定一个记录作为轴值,并把它与第一个记录交换,则一次划分后得到期望均衡的两个子序列,,从而使算法的行为不受待排序序列的不同输入实例的影响,使快速排序在最坏的情况下的时间性能趋近于 平均情况的时间性能。
随机化快速排序代码:
import java.util.Random;
public class RandomQuickSort {
/**
* @param args
* 随机化快速排序
*
*/
private static Random rnd=new Random();
public static void main(String[] args) {
// TODO Auto-generatedmethod stub
//定义一维数组
int[] R ={132,24,4,436,547,65,87,8,6,9,780,7,325,57,54,46,35,3,42,4};
//掉用quickSort方法,对一维数组排序,初始化low为0,最大值
quickSort(R, 0, R.length - 1);
//用for循环输出排序好的数组
for(int i = 0; i < R.length; i++) {
System.out.print(R[i] + " ");
}
}
//快速排序
//定义quickSort方法
static void quickSort(int R[], int low, int height) {
//对记录R[low...height]进行快速排序
if(low < height) {
int result = partition(R, low,height);
quickSort(R, low, result -1);
quickSort(R, result + 1,height);
}
}
//定义partition方法
static int partition(int R[], int low, int height) {
int point = rnd.nextInt(height-low)+low;
int temp = R[low];
R[low]= R[point];
R[point]= temp;
//交换记录子序列 R[low...height]的记录,使轴记录交换到正确的位置,并返回其所在的位置
int key = R[low]; //使用key存放枢轴记录的关键字
while(low < height) {
//从表的两端交替向中间扫描
while(low < height && R[height] >=key) {
height--;
}
R[low] = R[height]; //将比轴小的记录移到低端
while(low < height && R[low] <= key){
low++;
}
R[height] = R[low]; //将比轴大的记录移到高端
}
R[low] = key; //轴记录到位
return low; //返回轴记录位置
}
}