一、概述

快速排序又是一种分而治之思想在排序算法上的典型应用。本质上来看,快速排序应该算是在冒泡排序基础上的递归分治法。

快速:

它是处理大数据最快的排序算法之一了。

快速排序的最坏运行情况是 O(n²),比如说顺序数列的快排。

但它的平摊期望时间是 O(nlogn),且 O(nlogn) 记号中隐含的常数因子很小,比复杂度稳定等于 O(nlogn) 的归并排序要小很多。

所以,对绝大多数顺序性较弱的随机数列而言,快速排序总是优于归并排序。

 

二、算法步骤

1、pivot

从数列中挑出一个元素,称为 "基准"(pivot);

2、partition

分区(partition)操作:pivot的左小右大。在这个分区退出之后,该基准就处于数列的中间位置。

具体操作方案:

①两个指针left,right

②pivot默认是left的元素

③第一趟从right向左扫描,遇到比pivot小的(右小),把right赋值给left,并换到left向右扫描。

④从left向右扫描,遇到比pivot大的(左大),把left赋值给right,并换到right。

⑤终止条件:while(left<right)

3、递归

递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序;

终止条件:

if (arr == null || left >= right) {
    return;
}

 

 三、例子

 

 

 

 

参考:

快速排序法详解 不懂不要钱

 

四、代码

 

package 排序算法;

public class ClassicSortMethods {

    public static void main(String[] args) {
        int[] arr = {1, 112, -13, 24, -21, 12};
        ClassicSortMethods sm = new ClassicSortMethods();
        sm.quickSort(arr, 0, arr.length - 1);
        for (int num : arr) {
            System.out.print(num + " ");
        }
        System.out.println();
    }


    /**
     * 快速排序:
     * <p>
     * 平均快于O(nlogn)的算法
     * 大数据最快
     * 本质是,在冒泡基础上的递归分治法
     * 思想:pivot,小的放前面,大的放后面,分为两部分后递归。
     * 如何分成两部分:【好吧,搞半天理解错思路了,好像当成选择排序了。。。,快排要有左右两个指针,来回换着比较,这样才不会丢!】
     */
    public void quickSort(int[] arr, int left, int right) {
        if (arr == null || left >= right) {
            return;
        }
        int pivot_index = partition(arr, left, right);
        quickSort(arr, left, pivot_index - 1); //这里的end应该是pivot,因为end本身取不到值,如果减一会丢掉一个数!
        quickSort(arr, pivot_index + 1, right);
    }

    /**
     * 分区,走一趟,返回的是pivot的下标。
     * 两个指针,分别从左右走,先从右开始,一旦发生交换,就从对侧开始走。
     * 直到重合,就把pivot值赋给它,也就是要返回的下标位置。
     */
    private int partition(int[] arr, int left, int right) {
        if (arr == null || left >= right) {
            return -1;
        }
        int pivot = arr[left];
        while (left < right) {
            while (left < right && arr[right] >= pivot) {
                right--;
            }
            arr[left] = arr[right]; //右小时,把右边的值赋给left,然后就要从左开始了。

            while (left < right && arr[left] <= pivot) {
                left++;
            }
            arr[right] = arr[left];//左大,要吧左边的值赋值给right,然后又要从右开始了。
        }//退出循环时,left=right
        arr[left] = pivot;
        return left;
    }

}

 

posted on 2021-05-26 02:56  西伯尔  阅读(75)  评论(0编辑  收藏  举报