1 归并排序

思路:准备一个help数组,进行merge操作

  1. public static void mergeSort1(int[] arr) {
  2. if (arr == null || arr.length < 2) {
  3. return;
  4. }
  5. process(arr, 0, arr.length - 1);
  6. }
  7. public static void process(int[] arr, int left, int right) {
  8. if (left == right) {
  9. return;
  10. }
  11. //求中点
  12. int mid = left + ((right - left) >> 1);
  13. process(arr, left, mid);
  14. process(arr, mid + 1, right);
  15. merge(arr, left, mid, right);
  16. }
  17. //进行merge操作
  18. public static void merge(int[] arr, int left, int mid, int right) {
  19. int[] help = new int[right - left + 1];
  20. int l = left;
  21. int r = mid + 1;
  22. int i = 0;
  23. while (l <= mid && r <= right) {
  24. help[i++] = arr[l] <= arr[r] ? arr[l++] : arr[r++];
  25. }
  26. while (r <= right) {
  27. help[i++] = arr[r++];
  28. }
  29. while (l <= mid) {
  30. help[i++] = arr[l++];
  31. }
  32. System.arraycopy(help, 0, arr, left, help.length);
  33. }
  1. public static void mergeSort2(int[] arr) {
  2. if (arr == null || arr.length < 2) {
  3. return;
  4. }
  5. int step = 1;
  6. int length = arr.length;
  7. while (step < length) {
  8. int left = 0;
  9. while (left < length) {
  10. int mid = 0;
  11. //考虑边界和溢出
  12. if (length - left > step) {
  13. mid = left + step - 1;
  14. } else {
  15. mid = length - 1;
  16. }
  17. //考虑边界和溢出
  18. int right = 0;
  19. if (length - mid - 1 > step) {
  20. right = mid + step;
  21. } else {
  22. right = length - 1;
  23. }
  24. merge(arr, left, mid, right);
  25. if (right == length - 1) {
  26. break;
  27. } else {
  28. left = right + 1;
  29. }
  30. }
  31. if (step > (length >> 1)) {
  32. break;
  33. }
  34. step *= 2;
  35. }
  36. }
  37. public static void merge(int[] arr, int left, int mid, int right) {
  38. int[] help = new int[right - left + 1];
  39. int l = left;
  40. int r = mid + 1;
  41. int i = 0;
  42. while (l <= mid && r <= right) {
  43. help[i++] = arr[l] <= arr[r] ? arr[l++] : arr[r++];
  44. }
  45. while (r <= right) {
  46. help[i++] = arr[r++];
  47. }
  48. while (l <= mid) {
  49. help[i++] = arr[l++];
  50. }
  51. System.arraycopy(help, 0, arr, left, help.length);
  52. }

2 快速排序

不改进的
1)把数组范围中的最后一个数作为划分值,然后把数组通过荷兰国旗问题分成三个部分:左侧<划分值、中间==划分值、右侧>划分值
2)对左侧范围和右侧范围,递归执行
3)时间复杂度:08 归并排序和快排序 - 图1

  1. public static void quickSort(int[] arr) {
  2. if (arr == null || arr.length < 2) {
  3. return;
  4. }
  5. process(arr, 0, arr.length - 1);
  6. }
  7. public static void process(int[] arr, int left, int right) {
  8. if (left >= right) {
  9. return;
  10. }
  11. int[] equalE = partition(arr, left, right);
  12. process(arr, left, equalE[0] - 1);
  13. process(arr, equalE[1] + 1, right);
  14. }
  15. public static int[] partition(int[] arr, int left, int right) {
  16. int lessR = left - 1;
  17. int moreL = right;
  18. int i = left;
  19. while (i < moreL) {
  20. if (arr[i] < arr[right]) {
  21. swap(arr, ++lessR, i++);
  22. } else if (arr[i] > arr[right]) {
  23. swap(arr, i, --moreL);
  24. } else {
  25. i++;
  26. }
  27. }
  28. swap(arr, moreL, right);
  29. return new int[]{lessR + 1, moreL};
  30. }

改进的
1)在数组范围中,等概率随机选一个数作为划分值,然后把数组通过荷兰国旗问题分成三个部分:左侧<划分值、中间==划分值、右侧>划分值
2)对左侧范围和右侧范围,递归执行
3)时间复杂度为:08 归并排序和快排序 - 图2
4)额外空间复杂度:08 归并排序和快排序 - 图3

public static void quickSort(int[] arr) {
        if (arr == null || arr.length < 2) {
            return;
        }

        process(arr, 0, arr.length - 1);
    }

    public static void process(int[] arr, int left, int right) {
        if (left >= right) {
            return;
        }
        //等概率随机选一个值作为划分值
        swap(arr,left+(int) (Math.random()*(right-left+1)),right);

        int[] equalE = partition(arr, left, right);
        process(arr, left, equalE[0] - 1);
        process(arr, equalE[1] + 1, right);
    }


    public static int[] partition(int[] arr, int left, int right) {
        int lessR = left - 1;
        int moreL = right;
        int i = left;
        while (i < moreL) {
            if (arr[i] < arr[right]) {
                swap(arr, ++lessR, i++);
            } else if (arr[i] > arr[right]) {
                swap(arr, i, --moreL);
            } else {
                i++;
            }
        }
        swap(arr, moreL, right);
        return new int[]{lessR + 1, moreL};
    }