📜  合并排序与插入排序(1)

📅  最后修改于: 2023-12-03 14:50:40.195000             🧑  作者: Mango

合并排序与插入排序

简介

合并排序与插入排序是两种常见的排序算法。两者各有优点,对于不同的数据规模和数据类型可以选择不同的算法。

  • 合并排序:分治思想,先将数组分成两半,分别排序,再将两个有序的数组合并成一个有序数组。
  • 插入排序:对于待排序的数据,在已排序的序列中从后向前扫描,找到相应位置并插入。
合并排序的实现
递归版
public static void mergeSort(int[] nums, int left, int right) {
    if (left >= right) {
        return;
    }
    int mid = (left + right) / 2;
    mergeSort(nums, left, mid);
    mergeSort(nums, mid + 1, right);
    merge(nums, left, mid, right);
}

public static void merge(int[] nums, int left, int mid, int right) {
    int[] temp = new int[right - left + 1];
    int i = left, j = mid + 1, k = 0;
    while (i <= mid && j <= right) {
        temp[k++] = nums[i] < nums[j] ? nums[i++] : nums[j++];
    }
    while (i <= mid) {
        temp[k++] = nums[i++];
    }
    while (j <= right) {
        temp[k++] = nums[j++];
    }
    System.arraycopy(temp, 0, nums, left, temp.length);
}
迭代版
public static void mergeSort(int[] nums) {
    int n = nums.length;
    for (int len = 1; len < n; len *= 2) {
        for (int i = 0; i < n - len; i += len * 2) {
            int left = i, mid = i + len - 1, right = Math.min(i + len * 2 - 1, n - 1);
            merge(nums, left, mid, right);
        }
    }
}

public static void merge(int[] nums, int left, int mid, int right) {
    int[] temp = new int[right - left + 1];
    int i = left, j = mid + 1, k = 0;
    while (i <= mid && j <= right) {
        temp[k++] = nums[i] < nums[j] ? nums[i++] : nums[j++];
    }
    while (i <= mid) {
        temp[k++] = nums[i++];
    }
    while (j <= right) {
        temp[k++] = nums[j++];
    }
    System.arraycopy(temp, 0, nums, left, temp.length);
}
插入排序的实现
直接插入排序
public static void insertionSort(int[] nums) {
    for (int i = 1; i < nums.length; i++) {
        int j = i;
        int temp = nums[j];
        while (j > 0 && temp < nums[j - 1]) {
            nums[j] = nums[j - 1];
            j--;
        }
        nums[j] = temp;
    }
}
折半插入排序
public static void binaryInsertionSort(int[] nums) {
    for (int i = 1; i < nums.length; i++) {
        int low = 0, high = i - 1;
        int temp = nums[i];
        while (low <= high) {
            int mid = (low + high) / 2;
            if (nums[mid] < temp) {
                low = mid + 1;
            } else {
                high = mid - 1;
            }
        }
        for (int j = i; j > low; j--) {
            nums[j] = nums[j - 1];
        }
        nums[low] = temp;
    }
}
总结
  • 合并排序的时间复杂度为 $O(n\log n)$,空间复杂度为 $O(n)$。
  • 插入排序的时间复杂度为 $O(n^2)$,空间复杂度为 $O(1)$。
  • 当数据规模较小或已经部分有序时,插入排序的效率较高。当数据规模较大且无序时,合并排序的效率较高。