参考书籍:大话数据结构P417
动图:https://www.cs.usfca.edu/~galles/visualization/ComparisonSort.html,j控制右往左走,i控制左往右
不要急着写代码,先捋思路,可以先参照代码进行理解
快排基本思想是:通过一趟排序将待排记录分割成独立的两部分,其中基准值的左边都比基准值小,基准值的右边都比基准值大,则分别对这两部分进行递归排序,以达到有序的目的
以从小到大排序为例,首先选左边第一个为基准值(当然你也可以选其他),然后设置两个指针,从右往左找到比基准值小的数然后与基准值交换,相当于比基准值小的换到左边,再从左往右,找到比基准值大的然后与基准值交换,相当于比基准值大的换到右边
过程如图,一遍排序之后,基准值就会到中间,左边均小于基准值,右边则均大于
{20,10,40 ,50, 70,80,60,90}
不过还没排好序,还需要对左右两边进行递归排序,不断重复此过程,r表示右“指针”,L表示左“指针”
代码实现如下:
package Sort;
import java.util.Arrays;
public class QuickSort {
public static void main(String[] args) {
int[] arr = {50,10,90,70,40,80,60,20};
quickSort(arr, 0, arr.length-1);
}
public static void quickSort(int[] arr,int left,int right){
int pivot=0;//基准值的索引
if(left=pivotkey)
{
right--;
}
//比基准值小的数与基准值交换,即放在基准值的左边
swap(arr,left,right);
//找到比基准值大的
while(left
为什么外面已经有left
这是因为内循环改变了left和right的值,不做判断就会在里面的while循环一直循环
为什么以左边为基准值要从右开始找?(以右边为基准值要从左开始找)
如图,
思路
第二次写
package Sort;
import java.util.Arrays;
public class QuickSort {
public static void main(String[] args) {
QuickSort sort = new QuickSort();
int arrs[] = {5,2,1,3,4};
sort.qSort(arrs, 0, arrs.length-1);
System.out.println(Arrays.toString(arrs));
}
public void qSort(int[] arrs,int left,int right) {
if(left>=right)
return;
int pivot=partion(arrs, left, right);//基准值
//左递归
qSort(arrs, left, pivot-1);
//右递归
qSort(arrs, pivot+1, right);
}
public int partion(int arrs[],int left,int right)
{
int pivotKey = arrs[left];//选左边第一个为基准值
while(left=pivotKey)//右往左
{
right--;
}
//交换
int temp=arrs[left];
arrs[left]=arrs[right];
arrs[right]=temp;
while(left
时间:最好的情况,分区函数每次都分得很平均,这时候递归树的深度log2n ,每次分区排序时间为O(N) , 所以最好的情况是O(nlogn)。最坏的情况,序列逆序,每次划分只比上次划分少一个记录的子序列,另一个序列为空,此时递归树画出来就是一颗斜树,大约需要进行n次分区操作,每次分区平均扫描N/2次,最终时间复杂度为N^2
总结:两个函数一个递归,一个每次分区排序返回基准值
和归并排序相似,也是用到了递归与合并,使子序列有序,最终整个序列有序
快排之所以快,每次交换是跳着换,而冒泡是相邻交换,首尾交换为例,快排直接1次对换,而冒泡要换n-1次
快排的优化
排序的快慢取决于每次取决于关键字在整个序列的位置,太小或者太大都会影响性能,而且在现实中,待排序序列极有可能是基本有序的,这样每次选择第一个数作为基准值极不合理。
所以就有了三数取中(九数取中也可以)
- 即三个关键字取中间值,一般是左端中间右端三个数,也可以随机选取,随机数生成本身会带来时间上的开销,因此不予考虑
- 覆盖替代交换,少掉很多不必要的交换
- 在序列小于某个常数时7/50【来自参考资料】,使用插入排序,在小数组的情况下,插入排序要优于快排,因为快排用到了递归操作,在大数据量的情况下,则可以忽略这个影响
- 尾递归优化?大话数据结构第四点