描述
该算法维护一个有序序列,然后把无序序列中的元素,在有序序列中从后往前进行扫描,找到位置后插入。从一个元素开始,该元素可以认为已经被排序好的。在有序序列从后往前扫描的过程中,也要将已排序的元素逐个后移,为新插入的元素提供位置
代码实现
/**
* 插入排序
*/
public class InsertSort {
public static void main(String[] args) {
int[] arr = {3, 9, -1, 10, -20};
for (int i = 1; i < arr.length; i++) {
int insertVal = arr[i];
int insertIndex = i - 1;
//无序组的第一个,从后往前跟有序组对比,对比过程中,有序组后移
while (insertIndex >= 0 && insertVal < arr[insertIndex]) {
arr[insertIndex + 1] = arr[insertIndex];
insertIndex--;
}
arr[insertIndex + 1] = insertVal;
System.out.println(Arrays.toString(arr));
}
}
}
性能
插入排序算法在每轮排序中会使一个无序序列元素从后往前更有序序列对比,也就是最终需要 n-1 轮这样的排序(n 为待排序的数列的长度),而在每轮排序中都需要跟有序序列元素进行比较,在最坏的情况下,每次比较之后都需要交换位置,所以这里的最坏时间复杂度是 O(n^2)。其实插入排序在最好的情况下,最好时间复杂度可以达到 O(n),这当然是在待排序的数列有序的情况下。在待排序的数列本身就是我们想要的排序结果时,时间复杂度的确是 O(n),因为只需要一轮排序并且不用交换。但是实际上这种情况很少,所以插入排序的平均时间复杂度是 O(n^2)。
对于空间复杂度来说,插入排序用到的额外的存储空间只有一个,那就是用于交换位置的临时变量,其他所有操作都是在原有待排序列上处理的,所以空间复杂度为 O(1)。
插入排序是稳定的,因为在比较过程中,只有后一个元素比前面的元素大时才会对它们交换位置,对于同样大小的元素,是不需要交换位置的,所以对于同样大小的元素来说,相对位置是不会改变的。
排序发生在内存中,所以排序方式是内排序