什么是快排?
快排是对冒泡排序的一种改进,通过多次比较和交换来实现排序,排序的流程如下
(1)首先设定一个分界值,通过该分界值将数组分成左右两部分。
(2)将大于或等于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边。此时,左边部分中各元素都小于分界值,而右边部分中各元素都大于或等于分界值。
(3)然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理。
(4)重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。当左、右两个部分各数据排序完成后,整个数组的排序也就完成了
快排的时间复杂度
想要更好的计算时间复杂度,我们必须了解快排的思想,首先 快排第一次需要完全遍历一次数组,来将比分界值
小的移动到分界值的左边,比分界值大的,移动到分界值的右边,然后分别再对分界值两边的数组进行同样的操作
理想的情况是,每次划分所选择的中间数恰好将当前序列几乎等分,经过log2n趟划分,便可得到长度为1的子表。这样,整个算法的时间复杂度为O(nlog2n)
。
最坏的情况是,每次所选的中间数是当前序列中的最大或最小元素,这使得每次划分所得的子表中一个为空表,另一子表的长度为原表的长度-1。这样,长度为n的数据表的快速排序需要经过n趟划分,使得整个排序算法的时间复杂度为O(n2)
为了改善快速排序最差的情况,我们引入了三数取中
和随机数
两种选择分界值
的的方法,本文只演示其中随机数的方法
所需要栈的最大深度为O(log2n), 所以空间复杂度为O(log2n)
public class QuickSort {
public static void main(String[] args) {
int[] ints1 = {1,4,5,2,3,6,9,8,7};
quickSort(ints1);
for (int re : ints1) {
System.out.print(re + "-");
}
}
public static int[] quickSort(int[] nums){
quick(nums,0,nums.length-1);
return nums;
}
public static void quick(int[] nums, int begin, int end){
if(begin >= end){
return;
}
//取得中间值
int rPartition = randomPartition(nums,begin, end);
// 将中间值放到数组的第一个位置
swap(nums,begin,rPartition);
int partition = partition(nums,begin,end) ;
quick(nums,begin,partition-1);
quick(nums,partition+1,end);
}
// 根据随机数进行取中间值
public static int randomPartition(int start, int end){
Random r = new Random();
int val = r.nextInt(start,end);
return val;
}
public static int partition(int[] nums, int begin, int end){
//把左边挖空 作为基准值
int tmp = nums[begin];
while(begin < end){
//挖空法,将最左侧挖空,然后持续交换左右的数,知道左右指针汇合
while(begin < end && nums[end] >= tmp){
end--;
}
// 当遇到右侧值小于左侧的时候,将右侧的值直接放到左侧的坑中,右侧变坑
nums[begin] = nums[end];
while(begin < end && nums[begin] <= tmp){
begin++;
}
// 这个时候,右侧又变成坑了,当遇到左侧值大于右侧的时候,把左侧的值放到右侧,左侧变坑
nums[end] = nums[begin];
}
// 当两指针相汇合的时候,说明这个地方 就应该是中间值的位置,把之前挖出来的值放进去
nums[begin] = tmp;
return begin;
}
/**
* 用于交换数组两个位置的值
* @param nums 需要被交换的数组
* @param a
* @param b
*/
public static void swap(int[] nums, int a, int b){
int tmp = nums[a];
nums[a] = nums[b];
nums[b] = tmp;
}
}
一次排序的过程如下