快速排序

50 阅读1分钟
  • 基本原理:查找一个基准值,根据该值对数组一分为二,一边是小于等于,一边是大于;对于拆分之后的两个数组继续进行上述操作。利用了分治思想

  • 参考文章:time.geekbang.org/column/arti…

  • 需要额外空间的方法:

public class QuickSort {
    public static void sort(int[] nums) {
        if (nums == null || nums.length < 2) {
            return;
        }
        doSort(nums, 0, nums.length - 1);
    }

    /**
     * 左闭右闭区间
     *
     * @param nums
     * @param startIdx
     * @param endIdx
     */
    private static void doSort(int[] nums, int startIdx, int endIdx) {
        // 必须要有结束条件
        if (endIdx <= startIdx) {
            return;
        }
        // 先将根据p分开
        int p = nums[endIdx];
        int[] lessArray = new int[endIdx - startIdx + 1];
        int[] moreArray = new int[endIdx - startIdx + 1];
        int lessIdx = 0;
        int moreIdx = 0;

        for (int i = startIdx; i < endIdx; i++) {
            if (nums[i] <= p) {
                lessArray[lessIdx++] = nums[i];
            } else {
                moreArray[moreIdx++] = nums[i];
            }
        }

        for (int i = 0; i < lessIdx; i++) {
            nums[startIdx + i] = lessArray[i];
        }
        nums[startIdx + lessIdx] = p;
        for (int i = 0; i < moreIdx; i++) {
            nums[startIdx + lessIdx + i + 1] = moreArray[i];
        }
        // 再递归
        doSort(nums, startIdx, startIdx + lessIdx - 1);
        doSort(nums, startIdx + lessIdx + 1, endIdx);
    }
}
  • 通过元素交换的方法
public class QuickSort {
    public static void sort(int[] nums) {
        if (nums == null || nums.length < 2) {
            return;
        }
        doSort(nums, 0, nums.length - 1);
    }

    /**
     * 左闭右闭区间
     *
     * @param nums
     * @param startIdx
     * @param endIdx
     */
    private static void doSort(int[] nums, int startIdx, int endIdx) {
        // 必须要有结束条件
        if (endIdx <= startIdx) {
            return;
        }
        int p = nums[endIdx];
        int slowIdx = startIdx;
        int fastIdx = startIdx;

        while (fastIdx <= endIdx) {
        // 如果慢指针的值小于等于基准,那就不用操作。慢指针往后移动就行;
            if (nums[slowIdx] <= p) {
                slowIdx++;
                // 为了防止快指针比满足慢指针慢,移动一下
                fastIdx = Math.max(fastIdx, slowIdx);
                continue;
            }
            // 如果到这里,情况是慢指针找到了大于基准值的,但是快指针还没找到小于等于基准值的。如果找到了,那就进里面交换
            if (nums[fastIdx] <= p) {
                swap(nums, fastIdx, slowIdx);
                slowIdx++;
            }
            // 不管怎么样,快指针都往后走一步
            fastIdx++;
        }

        doSort(nums, startIdx, slowIdx - 2);
        doSort(nums, slowIdx, endIdx);
    }

    private static void swap(int[] nums, int n1, int n2) {
        if (n1 >= nums.length || n2 >= nums.length) {
            throw new RuntimeException("n1 or n2 illegal");
        }
        int temp = nums[n1];
        nums[n1] = nums[n2];
        nums[n2] = temp;
    }
}