懵X排序算法:快速排序

原文地址:xeblog.cn/articles/17数组

快速排序基本思想

快速排序使用的是 分治思想,经过一趟排序将要排序的数据分割成独立的两部分,其中一部分的全部数据都比另一部分的全部数据都要小,而后再按此方法对这两部分数据分别进行快速排序,整个排序过程能够递归进行,以此达到整个数据变成有序序列。bash

实现思路

  • 设置一个基准值 k ,通常取数组第一个元素,以此值分割数组;
  • 设置两个扫描员,分别为 iji 指向数组的最低位j 指向数组的最高位
  • 首先由 j 开始从数组最高位往数组最低位(j--)扫描比 k 小的值,扫描到后中止扫描,并将该值填入 i 所处的位置,而后再由 i 开始从数组最低位 往数组最高位(i++)扫描比 k 大的值,扫描到后中止扫描,并将该值填入 j 所处的位置,ji 依次扫描,直至 ji 的位置相互重合后,将 k 的值填入重合处,此时,数组左侧的值均小于 k,右侧值均大于 k,完成这次排序;
  • 分别对数组左右两边的值作如上操做后便可完成快速排序。

演示图 测试

快速排序演示图.gif

代码实现

/** * 快速排序 * @param array 待排序数组 * @param begin 起点索引 * @param end 终点索引 */
    private static void fastSort(int[] array, int begin, int end) {
        // 递归终止条件,起点索引大于等于终点索引
        if (begin >= end) {
            return;
        }

        // 起点索引
        int i = begin;
        // 终点索引
        int j = end;
        // 基准值
        int k = array[begin];

        // 循环条件:起点索引小于终点索引
        while (i < j) {
            /* 这个循环是要扫描小于基准值的值,扫描到后退出循环, 循环条件:当前索引位的值大于等于基准值k(加等于号是防止相同数字交换而陷入死循环中), 且起点索引小于终点索引(防止数组下标出界) */
            while (array[j] >= k && i < j) {
                // 终点索引位从右至左逐个递减
                j--;
            }

            if (i < j) {
                // 将小于基准值的数移至左侧
                array[i] = array[j];
            }

            /* 这个循环是要扫描大于基准值的值,扫描到后退出循环, 循环条件:当前索引位的值小于等于基准值k(加等于号是防止相同数字交换而陷入死循环中), 且起点索引小于终点索引(防止数组下标出界) */
            while (array[i] <= k && i < j) {
                // 起点索引位从左至右逐个递增
                i++;
            }
            if (i < j) {
                // 将大于基准值的数移至右侧
                array[j] = array[i];
            }
        }
        if (array[j] != k) {
            // 基准值归位(数组的中间某个位置),归位后,基准值左侧都是小于基准值的数,右侧都是大于基准值的数
            array[j] = k;
        }
        // 递归将基准值左侧的数排序
        fastSort(array, begin, j - 1);
        // 递归将基准值右侧的数排序
        fastSort(array, j + 1, end);
    }
复制代码

测试排序spa

int[] array = {5, 6, 6, 4, 3, 5, 5};
System.out.println("排序前:" + Arrays.toString(array));
fastSort(array, 0, array.length - 1);
System.out.println("排序后:" + Arrays.toString(array));
复制代码

输出结果code

排序前:[5, 6, 6, 4, 3, 5, 5]
排序后:[3, 4, 5, 5, 5, 6, 6]
复制代码

快速排序的时间复杂度

平均时间复杂度: O(nlogn)
最坏时间复杂度: O(n^2) ,这种状况发生在排序数组为正序逆序的时候。
稳定性: 不稳定。cdn

相关文章
相关标签/搜索