java - 插入排序

一、什么是插入排序

插入排序(Insertion sort)是一种简单直观的排序算法。它的基本思想是将待排序序列分为已排序和未排序两部分,初始时已排序部分只有一个元素,然后从未排序部分逐个取出元素并插入到已排序部分的正确位置,直到所有元素都插入完毕。

具体步骤如下:

  1. 从待排序序列中取出第一个元素,认为它已经是排好序的。
  2. 取出下一个元素,在已排序的序列中从后向前扫描,将较大的元素向后移动,给当前元素找到合适的位置。
  3. 重复步骤2,直到找到当前元素的正确位置。
  4. 重复步骤2和步骤3,直到所有元素都插入完毕。

插入排序的时间复杂度取决于待排序序列的初始顺序。在最好的情况下,即序列已经有序,插入排序的时间复杂度为O(n),其中n为待排序序列的长度。在最坏的情况下,即序列逆序,插入排序的时间复杂度为O(n^2)。平均情况下,插入排序的时间复杂度也为O(n^2)。

插入排序相比于冒泡排序和选择排序,其性能更好一些,特别适用于对部分有序的序列进行排序。它的实现简单、稳定,并且对于小规模的数据排序效率较高。

二、代码实现

 public static void insertionSort(int[] nums){
        int size = nums.length;
        // 外循环:已排序元素数量为 1, 2, ..., n
        for(int i = 1 ; i < size ; i++){
            int base = nums[i];
            int j = i -1;
            // 内循环:将 base 插入到已排序部分的正确位置
            while(j >= 0 && nums[j] > base){
                nums[j+1] = nums[j];
                j--;
            }
            nums[j+1] = base;
        }
    }

三、算法特性 

时间复杂度: O(n^2),最差情况下,每次插入操作分别需要循环 n−1、n−2、…、2、1 次,求和得到 (n−1)n/2 ,因此时间复杂度为 O(n^2) 。在遇到有序数据时,插入操作会提前终止。当输入数组完全有序时,插入排序达到最佳时间复杂度 O(n) 。

空间复杂度:O(1)。

稳定排序:在插入操作过程中,我们会将元素插入到相等元素的右侧,不会改变它们的顺序。

四、插入排序的优势 

插入排序与快速排序

插入排序的时间复杂度为 O(n^2) ,而快速排序的时间复杂度为O(n^logn)。尽管插入排序的时间复杂度相比快速排序更高,但在数据量较小的情况下,n2 和 n^log⁡n的数值比较接近,复杂度不占主导作用,每轮中的单元操作数量起到决定性因素。快速排序这类 O(n^log⁡n) 的算法属于基于分治的排序算法,往往包含更多单元计算操作。因此插入排序通常更快。 一般的,长数组使用快速排序,短数组使用插入排序。

插入排序与冒泡排序、选择排序

虽然冒泡排序、选择排序和插入排序的时间复杂度都为 O(n^2) ,但在实际情况中,插入排序的使用频率显著高于冒泡排序和选择排序,主要有以下原因。 

  • 冒泡排序基于元素交换实现,需要借助一个临时变量,共涉及 3 个单元操作;插入排序基于元素赋值实现,仅需 1 个单元操作。因此,冒泡排序的计算开销通常比插入排序更高
  • 选择排序在任何情况下的时间复杂度都为 O(n^2) 。如果给定一组部分有序的数据,插入排序通常比选择排序效率更高
  • 选择排序不稳定,无法应用于多级排序。

参考:11.4   插入排序 - Hello 算法 (hello-algo.com) 

你可能感兴趣的:(数据结构,java,算法,排序算法)