Java基础随笔-快速排序(两种方法)

算法思想

快速排序(Quicksort)是对冒泡排序的一种改进,借用了分治的思想,由C. A. R. Hoare在1962年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

实现过程

1:从当前数组中取出一个元素作为一个基准值
2:从数组的后面开始往前取值和这个基准值对比,比它小就放到这个基准值的位置
3:从数组的前面开始取值和这个基准值对比,比它大就放到这个基准值后面
4:重复2,3操作直到往前找不到比它大的,往后找不到比它小的
5:进行递归调用

代码实现

第一种方法(称为挖坑法)

/**
 * ClassName:QuickSort1
 * Author:LFM
 * Date:2019/6/15 16:04
 **/
public class QuickSort1 {
    public static void sort(int [] arr, int low,int high){
        if (arr==null||arr.length<=0){
            return ;
        }
        if (low>=high){
            return;
        }

        int left = low;
        int right = high;
        int temp = arr[left];//挖坑1,保存这个基准值(假设是第一个元素)

        while (left<right){

            while (left<right && arr[right]>=temp){
                right--;//从后往前移逐步寻找比基准值小的数(相对于基准值)
            }
            arr[left] = arr[right];//挖坑2:从后向前找到比基准值小的元素,插入基准值位置坑1中

            while (left<right && arr[left]<=temp){
                left++;//从前往后逐步寻找比基准值大的数(相对于基准值)
            }
            arr[right] = arr[left];//挖坑3:从前向后找比基准值大的数,放到坑2中。
        }

        arr[left] = temp;//当left==right时(说明找到自己了,即后无小,前无大),将基准值放入坑3中,准备分治递归快排
        System.out.println("排序...:"+ Arrays.toString(arr));
        sort(arr,low,left-1);//这个就是做基准值左部分的排序(-1的目的就是除去基准值的位置)
        sort(arr,left+1,high);//这个就是基准值右部分的排序(+1也是同样道理,但是这里用high就是保证这右边的长度是除去基准值和左边后的长度)
    }

    public static void main(String[] args) {
        int [] arr = {4,3,7,5,10,9,1,6,8,2};
        System.out.println("排序前:"+Arrays.toString(arr));
        sort(arr,0,arr.length-1);
    }

}

运行结果

在这里插入图片描述
详细解释我都写在代码的注释里面了,唯一要解释的就是调用的时候要把数组的长度-1,因为我们取了一个元素作为基准值了。

第二种方法(左右指针法)

/**
 * ClassName:QuickSort2
 * Author:LFM
 * Date:2019/6/15 18:06
 **/
public class QuickSort2 {

    public static void sort2(int arr[], int low, int high) {
        if (arr == null || arr.length <= 0) {
            return;
        }
        if (low >= high) {
            return;
        }

        int left = low;
        int right = high;
        int key = arr[left];//相当于挖坑操作,选定一个基准值

        while (left < right) {
            while (left < right && arr[right] >= key) {
                right--;//从后往前找,符合之后记录right值
            }
            while (left < right && arr[left] <= key) {
                left++;//从前往后找,符合之后记录left值
            }
            if (left < right) {
                swap(arr, left, right);//交换数组下标和达到交换数组元素,这种方法就是把第一种占坑操作综合起来了
            }
        }
        swap(arr, low, left);//交换基准值和当前left=right的那个位置的元素
        System.out.println("排序后: " + Arrays.toString(arr));
        sort2(arr, low, left - 1);
        sort2(arr, left + 1, high);
    }

    public static void swap(int arr[], int low, int high) {
        int tmp = arr[low];
        arr[low] = arr[high];
        arr[high] = tmp;
    }

    public static void main(String[] args) {
        int [] arr = {4,3,7,5,10,9,1,6,8,2};
        System.out.println("排序前:"+Arrays.toString(arr));
        sort2(arr,0,arr.length-1);
    }
}

运行结果:

在这里插入图片描述
这种方法就是把通过交换数组的下标来交换元素,同时把元素之间的交换操作通过一个自定义函数完成。看上去比较简洁把,算法思想是一样的

时间复杂度

快速排序是不稳定的,因为每次交换的元素可能不是相邻
在这里插入图片描述
这个时间复杂度比较难理解,我看别人是这么推算的:

在这里插入图片描述
现在我还不会,也想不明白(数学不太好、时间不够了,等我工作时买了算法导论再来写一个详细的证明过程,现在先记住先)

猜你喜欢

转载自blog.csdn.net/weixin_42341232/article/details/92164636
今日推荐