Java语言实现快速排序

最近面试被问及次数最多的就是快排的算法,所以做了简单的梳理和实现,在此记录。

快排是利用分治法来对待排序序列,它的思想主要是定义一个基准值,之后通过一次排序将待排记录分隔成独立的两部分,基准值左边的数列都比基准值小,右边的数列都比基准值大,然后再对这两个数列分别采用这种方式进行排序,通过递归的方式最终使整个序列有序。

快速排序的一次划分算法从两头交替搜索,直到左右两个指针重合,因此其时间复杂度是O(n);而整个快速排序算法的时间复杂度与划分数列的次数有关。理想的情况是,每次划分所选择的中间数恰好将当前序列几乎等分,经过log2n趟划分,便可得到长度为1的子表。这样,整个算法的时间复杂度为O(nlog2n)。最坏的情况是,每次所选的中间数是当前序列中的最大或最小元素,这使得每次划分所得的子表中一个为空表,另一子表的长度为原表的长度-1。这样,长度为n的数据表的快速排序需要经过n趟划分,使得整个排序算法的时间复杂度为O(n2)。我们一般认为快排的时间复杂度是O(NlogN)。

快速排序不是稳定的排序算法,大小相同的两个数,经过快排后最终位置与初始位置有可能不同。当然也有可能相同(比如待排序记录中只有一组相同的数字,而选择的基数恰好是这组相同数字中的一个,此时的快速排序就是稳定的)

快排思路如下(转的):

我们从一个数组来逐步逐步说明快速排序的方法和思路。

假设我们对数组{7, 1, 3, 5, 13, 9, 3, 6, 11}进行快速排序。

首先在这个序列中找一个数作为基准数,为了方便可以取第一个数。

遍历数组,将小于基准数的放置于基准数左边,大于基准数的放置于基准数右边。

此时得到类似于这种排序的数组{3, 1, 3, 5, 6, 7, 9, 13, 11}。

在初始状态下7是第一个位置,现在需要把7挪到中间的某个位置k,也即k位置是两边数的分界点。

那如何做到把小于和大于基准数7的值分别放置于两边呢,我们采用双指针法,从数组的两端分别进行比对。

先从最右位置往左开始找直到找到一个小于基准数的值,记录下该值的位置(记作i)。

再从最左位置往右找直到找到一个大于基准数的值,记录下该值的位置(记作j)。

之后将两个坐标所指的元素进行交换,令较小的数字在左边,较大的数字在右边。

之后指针从之前i, j的位置继续向中间移动,即从j-1位置往前和i+1位置往后,重复上面比对基准数然后交换的步骤。

如果执行到i==j,表示本次比对已经结束,此时已经将数组全部比较了一遍。此时基准数base=[left]=最左面的数字,中位数=[i]/[j]。将最后i的位置的值与基准数做交换,此时基准数就找到了临界点的位置k,位置k两边的数组都比当前位置k上的基准值或都更小或都更大。

上一次的基准值7已经把数组分为了两半,基准值7算是已归位(找到排序后的位置)。

通过相同的排序思想,分别对7两边的数组进行快速排序,左边对[left, k-1]子数组排序,右边则是[k+1, right]子数组排序。

利用递归算法,对分治后的子数组进行排序。

Talk is cheap,直接show code(代码是自己写的):


/**

* @Auther: 杯酒暖天寒

* @Date: 2019-12-13 16:22

* @Description:实现快速排序

*/

public class QuickSort {

/**

* 快速排序实现

    * @param numbers 待排序的数组

    * @param left 基准值位置,一般选数组第一个元素

    * @param right 数组最后一个元素的下标

*/

    public static void quickSort(int [] numbers,int left,int right){

if (numbers ==null || numbers.length < 2 || left > right){
        return;
        }

        int i = left;
        int j = right;
        int base = numbers[left];

        while(i != j){
//从右往左找,找到比基准数小的数字,记录坐标
            while (numbers[j] >= base && i < j ){
                        j--;
            }
//从左往右找,找到比基准数字大的数字,记录坐标
            while (numbers[i] <= base && i < j ){
                      i++;
            }

//将找到的两个数字互换,得到新的数组
            if (i < j){
                int tmp = numbers[i];
                numbers[i] = numbers[j];
                numbers[j] = tmp;
            }
    }

//i = j时,基准数base = numbers[left],中位数 = numbers[i]
//将基准数和中位数互换,即基准数换到中位,分割成两个数列
        numbers[left] = numbers[i];
        numbers[i] = base;
        //两个数列递归排序
        quickSort(numbers, left, i-1);
        quickSort(numbers, i+1, right);
    }

public static void main(String[] args) {
        int numbers[] = {7,1,3,5,13,9,3,6,11};
        quickSort(numbers, 0, numbers.length-1);
        System.out.print(Arrays.toString(numbers));
    }
}

你可能感兴趣的:(Java语言实现快速排序)