插入排序之直接插入排序与希尔排序

直接插入排序-原理:
整个区间被分为

  1. 有序区间
  2. 无序区间 :每次选择无序区间的第一个元素,在有序区间内选择合适的位置插入。
    基本思想:
    直接插入插排的基本思想是:当插入第i(i >= 1)时,前面的array[0],array[1],……,array[i-1]已经排好序。这时,用array[cur]的排序码与V[i-1],V[i-2],…的排序码顺序进行比较,找到插入位置即将V[i]插入,原来位置上的元素向后顺移。
    实现:
// 以升序排序为例
    public static void insertSort(int[] array) {
        // 有序区间: [0, bound)
        // 无序区间: [bound, size)
        for (int bound = 1; bound < array.length; bound++) {
            // 处理 bound 位置的元素如何往前插入
            int tmp = array[bound];
            // 需要从后往前, 找到合适的位置进行插入.
            int cur = bound - 1;
            for (; cur >= 0; cur--) {
      // 如果这里的条件写成了 array[cur] >= tmp, 此时就是不稳定排序了
                if (array[cur] > tmp) {
       // tmp 元素还需要往前去找. 同时就需要把 cur 位置的元素往后搬运
                    array[cur + 1] = array[cur];
                } else {
                    break;
                }
            }
            array[cur + 1] = tmp;
        }
    }
    private static void Swap(int[] array, int i, int j) {
        int tmp = array[i];
        array[i] = array[j];
        array[j] = tmp;
    }

性能分析:
时间复杂度:O(n^2)
空间复杂度:O(1)
稳定性:稳定
插入排序,初始数据越接近有序,时间效率越高

希尔排序-原理:
希尔排序法又称缩小增量法。希尔排序法的基本思想是:先选定一个整数,把待排序文件中所有记录分成个组,所有距离为的记录分在同一组内,并对每一组内的记录进行排序。然后,取重复上述分组和排序的工作。当到达=1 时,所有记录在统一组内排好序。

  1. 希尔排序是对直接插入排序的优化。
  2. 当gap > 1时都是预排序,目的是让数组更接近于有序。当gap == 1时,数组已经接近有序的了,这样就会很快。这样整体而言,可以达到优化的效果。我们实现后可以进行性能测试的对比。
    实现:
 public static void shellSort(int[] array) {
        // size/2, size/4, size/8 ... 1
        int gap = array.length / 2;
        while (gap > 1) {
            insertSortGap(array, gap);
            gap = gap / 2;
        }
        // 当 gap 为 1 的时候, 再来一次最终插排
        insertSortGap(array, 1);
    }

    // 分组情况下, 同组的相邻元素下标差 gap
    private static void insertSortGap(int[] array, int gap) {
        // 从每组的 [1] 的元素开始.
        for (int bound = gap; bound < array.length; bound++) {
            int tmp = array[bound];
            // bound 位置中相邻的前一个元素下标
            int cur = bound - gap;  
            for (; cur >= 0; cur -= gap) {
                if (array[cur] > tmp) {
              // 进行搬运, 把 cur 位置的元素搬到 cur + gap 位置
                    array[cur + gap] = array[cur];
                } else {
                    break;
                }
            }
            array[cur + gap] = tmp;
        }
    }
     private static void Swap(int[] array, int i, int j) {
        int tmp = array[i];
        array[i] = array[j];
        array[j] = tmp;
    }

希尔排序是直接插入排序的改进,我们在实现的时候,只要把gap看成1就好理解了。
性能分析:
时间复杂度:最坏情况下是O(n^2),最好情况下理论可以达到O(n ^1.3)
空间复杂度:O(1)
稳定性:不稳定

猜你喜欢

转载自blog.csdn.net/weixin_45755718/article/details/106066367
今日推荐