算法学习笔记--快速排序

前言

在学习左神的算法课,对快速排序有了更多的理解,在此记录,以备后查

快速排序1.0

描述:

快排1.0是基于单个支点进行递归操作。大体来讲,是选择数组arr中的某一个数作为支点pivot,经过一通操作(一般叫partition),使得左边的数均小于等于pivot,右边的数均>pivot,如此一来,pivot就待在了自已排好序的位置。然后再对左边和右边分别做同样的操作,就完成了整个数组的排序

代码:

    /**
     * 快速排序 1.0
     * @param arr
     * @param left
     * @param right
     */
    public static void quickSort1(int[] arr, int left, int right) {
        if (left >= right) {
            return;
        }
        //进行partition操作,返回支点的位置
        int pivot = partition1(arr, left, right);
        //对支点左边快排
        quickSort1(arr, left, pivot - 1);
        //对支点右边快排
        quickSort1(arr, pivot + 1, right);
    }

    /**
     * 以arr[right]作为支点值,j为右半边的
     * 左边界,curr指向当前待判断的数
     * @param arr
     * @param left
     * @param right
     */
    private static int partition1(int[] arr, int left, int right) {
        int j = right, curr = left;
        while (curr < j) {
            if (arr[curr] <= arr[right]) {
                curr++;
            }else {
                swap(arr,curr,--j);
            }
        }
        swap(arr, right, j);
        return j;
    }

快速排序2.0

描述:

快排2.0仍然是基于单个支点的递归,不同于1.0之处,在于数组中可能有多个值跟支点pivot相等,每次partition,可以把数组分成小于pivot、等于pivot、大于pivot这三部分,避免跟pivot相等的值重复参与partition

代码:

    /**
     * 快速排序 2.0
     * @param arr
     * @param left
     * @param right
     */
    public static void quickSort2(int[] arr, int left, int right) {
        if (left >= right) {
            return;
        }
        //进行partition操作,返回支点的位置
        int[] leftRight = partition2(arr, left, right);
        //对支点左边快排
        quickSort2(arr, left, leftRight[0]-1);
        //对支点右边快排
        quickSort2(arr,leftRight[1]+1, right);
    }

    /**
     * 以arr[right]作为支点值,i为左半边的有边界,j为右半边的
     * 左边界,curr指向当前待判断的数
     * @param arr
     * @param left
     * @param right
     * @return
     */
    private static int[] partition2(int[] arr, int left, int right) {
        if(left>=right){
            return new int[]{-1,-1};
        }
        int i=left-1, j = right, curr = left;
        while (curr < j) {
            if (arr[curr] < arr[right]) {
                swap(arr,++i,curr++);
            }else if(arr[curr]==arr[right]){
                curr++;
            }else {
                swap(arr,--j,curr);
            }
        }
        swap(arr, right, j);
        return new int[]{i+1,j};
    }

快速排序3.0

描述:

快排3.0相比于2.0,增加了一个随机因子,即不再固定选择arr[right]作为支点,而是在arr[]中随机选择一个。目的是为了减少最坏情况(性能退化为O(N2))发生的概率。

代码:

    /**
     * 快速排序 3.0
     * @param arr
     * @param left
     * @param right
     */
    public static void quickSort3(int[] arr, int left, int right) {
        if (left >= right) {
            return;
        }
        //随机选择一个,交换到arr[right]
        swap(arr,right,L+(int)Math.random()*(right-left+1));
        //进行partition操作,返回支点的位置
        int[] leftRight = partition2(arr, left, right);
        //对支点左边快排
        quickSort2(arr, left, leftRight[0]-1);
        //对支点右边快排
        quickSort2(arr,leftRight[1]+1, right);
    }

    /**
     * 以arr[right]作为支点值,i为左半边的有边界,j为右半边的
     * 左边界,curr指向当前待判断的数
     * @param arr
     * @param left
     * @param right
     * @return
     */
    private static int[] partition2(int[] arr, int left, int right) {
        if(left>=right){
            return new int[]{-1,-1};
        }
        int i=left-1, j = right, curr = left;
        while (curr < j) {
            if (arr[curr] < arr[right]) {
                swap(arr,++i,curr++);
            }else if(arr[curr]==arr[right]){
                curr++;
            }else {
                swap(arr,--j,curr);
            }
        }
        swap(arr, right, j);
        return new int[]{i+1,j};
    }

荷兰国旗问题

描述:

给定一个数组arr,和一个数num,请把小于num的数放在数组的左边,等于num的数放在数组的中间,大于num的数放在数组的右边。
要求额外空间复杂度O(1),时间复杂度O(N)

思路:

和快速排序2.0的一次partition操作基本一致,略有不同之处在于,num不是数组arr中的数,因而不需要arr[right]作为支点,右半边的左边界初始值应该从arr.length开始

代码:

/**
     * 荷兰国旗问题
     * @param arr
     * @return
     */
    private static int[] netherLandFlag(int[] arr, int num) {
        if(arr==null||arr.length<2){
            return arr;
        }
        int less=-1,more=arr.length;
        int curr=0;
        while (curr < more) {
            if (arr[curr] < num) {
                swap(arr,++less,curr++);
            }else if(arr[curr]==num){
                curr++;
            }else {
                swap(arr,--more,curr);
            }
        }
        return new int[]{less+1,more-1};
    }

你可能感兴趣的:(算法,java)