【排序算法】快速排序的详解

一、整体思路解析

1.首先选定待排序数组的第一个元素为基准值val
其中 l 是数组的初始位置,蓝色区域表示在区间[l+1,j]上所有的元素值都是小于v的,红色区域表示在区间[j+1,i-1]上,所有的元素值都大于等于v,i 索引表示当前正在遍历的元素索引位置
2.当 i 向后遍历过程中,分情况讨论
<2.1>如果当前遍历到的元素arr[i] > v 时,i++,红色区域增加即可;
在这里插入图片描述
i++后,就把大于等于v的元素加入到红色区域,i继续向后遍历;
<2.2>如果在遍历的过程中,arr[i] <v 时:
在这里插入图片描述

 for (int i = l+1; i <=r ; i++) {
            if (arr[i] <val){
                swap(arr,i,j+1);
                j++;
            }
        }

3.整个集合扫描完毕,整个区间就被我们分隔为以下情况:
在这里插入图片描述
4.经过以上步骤,arr[j]左侧元素均小于v,arr[j]之后的元素均 大于等于v,分区完成。继续在小于v的区间和大于v的区间继续递归上述过程,直至整个集合有序。

二、代码实现

代码如下(示例):

import java.util.Arrays;

/**
 * 快速排序
 * 时间复杂度:Nlogn
 * 不稳定的排序算法
 */
public class QuickSort {
    /**
     * 快速排序
     * @param arr
     */
    public static void quickSort(int[] arr){
        quickSortInternal(arr,0,arr.length-1);
    }
    /**
     * 在区间【l,r】上进行快速排序
     * @param arr
     * @param l
     * @param r
     */
    private static void quickSortInternal(int[] arr, int l, int r) {
        //先获取分区点:经过分区函数后,某个元素落在了最终的位置
        //分区点左侧元素均小于该元素,分区点右侧元素均大于等于该元素
        if (r-l<=15){
            //优化点,在元素小于15时,直接插入排序优化算法
            insertSort(arr,l,r);        
            return;
        }
        //分区函数,最终返回在[l,r]区间上分区点元素索引
        int p=partition(arr,l,r);
        //在分区元素左侧区间递归
        quickSortInternal(arr,l,p-1);
        //在分区元素右侧区间递归
        quickSortInternal(arr,p+1,r);
    }

    /**
     * 分区函数
     * @param arr
     * @param l
     * @param r
     * @return 分区点索引
     */
    private static int partition(int[] arr, int l, int r) {
        //基准值
        int val=arr[l];
        //arr[l+1...j] < val
        //arr[j+1...i) >= val
        // i 表示当前正在扫描的元素索引
        int j=l;
        for (int i = l+1; i <=r ; i++) {
            if (arr[i] <val){
                swap(arr,i,j+1);
                j++;
            }
        }
        //经过上述循环,就把小于val的元素换到了分区点的左侧
        //此时,将基准值和最后一个小于v的元素交换,基准值就落在了最终的位置
        swap(arr,j,l);
        return j;
    }

    /**
     * 交换数组中 i 和 j 的索引
     * @param arr
     * @param j
     * @param i
     */
    private static void swap(int[] arr, int i, int j ) {
        int temp=arr[i];
        arr[i] =arr[j];
        arr[j] = temp;
    }
    /**
     * 在区间[l , r]上进行插入排序
     * @param arr
     * @param l
     * @param r
     */
    private static void insertSort(int[] arr, int l, int r) {
        for (int i=l+1;i<=r;i++){
            for (int j=i; j>l&& arr[j]<arr[j-1];j--){
                swap(arr,j,j-1);
            }
        }
   	 }
    }

总结
1.基准值默认选择左侧区间的第一个元素,也可以是其他位置元素;
2.在快速排序中,当数组元素小于等于15时,进行插入排序优化算法;
3.区间的定义一定要明确,边界值的判断要清晰。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值