快速排序详解

1、什么是快速排序?

        快速排序是通过比较和交换位置来排序的排序算法,是对冒泡算法的一种优化。

2、什么时候使用快速排序?

        当数据量比较大的时候,推荐使用快速排序。

3、快速排序的主要思想是什么?

        快速排序的思想是:通过一次排序将无序的数据分为两个独立部分,其中一部分数据的值均比另一部分要小,再对这两部分分别进行排序,使得整个序列有序。简单来说,就是从所有数据中取一个基准值,不大于该基准值的为一部分,大于基准值的为一部分,再在这两部分中分别取基准值再继续分别分为两部分,以此类推,直到剩下的部分只有一个元素,则结束。

4、快速排序的步骤是什么?

快速排序的两种方法:填坑法和前后指针法

填坑法步骤:

  1. 取序列A中第一个元素为基准值,并且取两个索引i=0,j=n-1,准备临时变量temp = A[i];
  2. 从右开始寻找小于基准值temp的数(j-- && j > i),得到值A[j],填坑:A[i]=A[j]
  3. 从左开始寻找不小于基准值temp的数(i++ &&  j>i),得到值A[i],填坑:A[j]=A[i]
  4. 重复操作2和操作3,直到i==j,则A[i]=temp
  5. 将序列分为0 ~ i-1 和i+1 ~ n-1两部分,继续重复步骤1、2、3、4,直到最后的序列只剩下一个元素。

填坑法的重点:不动的指针所指的位置是坑位

如图:

前后指针法的步骤:

  1. 取序列A中第一个元素为基准值,并且取两个索引i=0,j=n-1,准备临时变量begin= i;
  2. 从右开始寻找不大于基准值temp的数(j-- && j > i),得到值A[j]
  3. 从左开始寻找大于基准值temp的数(i++ &&  j>i),得到值A[i],交换值A[i]和值A[j]
  4. 重复操作2和操作3,直到i==j,交换A[i]和A[begin]的值
  5. 将序列分为0 ~ i-1 和i+1 ~ n-1两部分,继续重复步骤1、2、3、4,直到最后的序列只剩下一个元素。

如图:

5、快速排序的java代码

填坑法Java代码:

public class quickSort1 {

    public static void main(String[] args) {
        int[] arr = {0, 3, 7, 5, 1, 2, 8, 3, 2, 1, 5, 6, 2,
                3, 4, 9, 1, 3, 4, 2, 3, 4, 4, 5, 3, 1, 8};
        int begin = 0;
        int end = arr.length - 1;
        quickSort(arr, begin, end);
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
    }

    /**
     * 填坑法
     *
     * @param arr   序列
     * @param begin 开始值
     * @param end   结束值
     */
    private static void quickSort(int[] arr, int begin, int end) {
        if (begin >= end) {
            return;
        }
        // 用于标记划分区域的大小
        int m = begin;
        int n = end;
        // 获得基准值
        int temp = arr[m];
        while (m != n) {
            // 注意序列中和基准值相同的元素,不然会死循环
            while (m < n && arr[n] >= temp) {
                n--;
            }
            arr[m] = arr[n];
            while (m < n && arr[m] < temp) {
                m++;
            }
            arr[n] = arr[m];
            if (n == m) {
                arr[m] = temp;
            }
        }
        // 迭代
        quickSort(arr, begin, m - 1);
        quickSort(arr, m + 1, end);
    }
}

前后指针交换法:

public class quickSort1 {

    public static void main(String[] args) {
        int[] arr = {0, 3, 7, 5, 1, 2, 8, 3, 2, 1, 5, 6, 2,
                3, 4, 9, 1, 3, 4, 2, 3, 4, 4, 5, 3, 1, 8, 10};
        int begin = 0;
        int end = arr.length - 1;
        quickSort(arr, begin, end);
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
    }

    /**
     * 前后指针法
     *
     * @param arr 数组
     * @param begin 开始
     * @param end 结束
     */
    private static void quickSort(int[] arr, int begin, int end) {
        if (begin >= end) {
            return;
        }
        int temp = arr[begin];
        int i = begin;
        int j = end;
        while (i != j) {
            // 必须先从右边来其获取的是arr[j] <= temp
            while (i < j && arr[j] > temp) {
                j--;
            }
            while (i < j && arr[i] <= temp) {
                i++;
            }
            int tb = arr[j];
            arr[j] = arr[i];
            arr[i] = tb;
        }
        // 交换初始值和i==j的值
        arr[begin] = arr[i];
        arr[i] = temp;
        // 迭代
        quickSort(arr, begin, i - 1);
        quickSort(arr, i + 1, end);
    }
}

6、快速排序代码中的疑问解答

        1、为什么比较的时候必须有“>=”,不能都使用“>”吗?

                不能,因为序列中可能存在和基准值一样大小的值,如果没有“=”,可能会出现死循环。

        2、为什么从左边开始选基准值,要先从右边开始找不大于基准值的值?

                主要是如果从右边开始找最差的情况是找到的值和基准值相等,这样的值还是可以放到基准值的左边的,如果从左边开始寻找,因为其找的是不小于基准值的值,这样的值最后放到了基准值的左边,但是左边的元素是不大于基准值,所以报错,例如序列{5,6,4,5,7},假如基准值为4,如果从左边开始找到的值找到为5,放到左侧报错,从右侧找,找到了值为4,不会出现问题。

7、快速排序和冒泡算法比较

        快速排序其根据选取的基准值可以使序列中的数据远距离交换,但是冒泡排序只能是相邻元素之间的交换,快速排序的比较和交换次数相对而言比较少,所以快速排序的效率比较高。

时间复杂度空间复杂度稳定性
快速排序nlognlogn不稳定
冒泡排序1稳定

        快速排序时间复杂度最差的情况是:n²,这种情况下序列本来就是有序,基准值每次都选的是最大或者最小值。而快速排序的稳定性,则是快排会导致相同元素的相对位置发生改变,如:{3,4,2,6,2,6},这会导致2和4交换,会导致2的相对位置发生改变,所以是不稳定的

8、快速排序的总结

        快速排序是一种分而治之的思想,通过基准值将序列划分为两段小序列,然后继续划分,直到划分到只有一个元素或者为空的序列,结束继续划分。其最坏时间复杂度是O(n²),平均的时间复杂度为O(nlogn),空间复杂度为O(logn),是一种不稳定算法。

9、快速排序类比

        快速排序的类比:快速排序可以类比为建立一棵二叉树,其选取的基准值可以理解为父节点,其分的两部分可以理解为左子树集和右子树集。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值