前边分别讨论了冒泡排序和选择排序,并分析了二者时间复杂度及性能优劣。这里继续介绍另一种排序算法:直接插入排序。这是一种比前二者性能都要好些的排序方法。
所谓插入排序,由字面上不难猜出就是把相对较小(从小到大排序)的元素插入到数组中准确的位置实现有序数组的生成。
定义:直接插入排序(Straight Insertion Sort)的基本操作是将一个记录插入到已经排好序的有序表中,从而得到一个新的有序表,同时记录数增长1。
上述定义中所说的已经排好序的有序表也就是事先假定数组中要进行插入的元素之前(针对小标而言)的一部分数据自成一个有序序列(其后的为无序序列),按照大小依次将当前元素插入到准确的位置,完成有序序列的生成。
下边来看java实现代码:
public static void sort(int[] arr) {
for (int i = 1; i < arr.length; i++) {
int temp = arr[i]; // 保存可能要被插入到准确位置的数值
int j = i - 1;
while (j >= 0 && temp < arr[j]) { // 要被插入的数值小于第j个元素的数值
arr[j + 1] = arr[j]; // 将第j个元素向后移动,将其原来位置留给要被插入的数值
j--;
}
arr[j + 1] = temp; // 也就是把每次循环得到的相对较小的元素的数值插入到准确位置
}
}
public static void main(String[] args) {
int[] arr = {12, 5, 14, 24, 31, 25, 57, 18, 9, 21};
sort(arr);
for (int temp : arr) {
System.out.print(temp + " ");
}
}
老套路,演示排序流程:
排序前: 12 5 14 24 31 25 57 18 9 21
第一次: 5 12 14 24 31 25 57 18 9 21
第二次: 5 12 14 24 31 25 57 18 9 21
第三次: 5 12 14 24 31 25 57 18 9 21
第四次: 5 12 14 24 31 25 57 18 9 21
第五次: 5 12 14 24 25 31 57 18 9 21
第六次: 5 12 14 24 25 31 57 18 9 21
第七次: 5 12 14 18 24 25 31 57 9 21
第八次: 5 9 12 14 18 24 25 31 57 21
第九次: 5 9 21 12 14 18 24 25 31 57
继续分析其时间复杂度:
在理想的情况下,也就是序列本来就是有序的,不需要进行数据的插入,但是还是需要进行数据的大小比较,此时其时间复杂度为O(n)。在最“糟糕”的情况下,也就是倒序的时候,除了需要进行1 + 2 + ... + (n - 1)次比较外,还需要进行2 + 3 + ... + n次插入操作,共为 n * (n - 1) / 2 + (n + 2) * (n -1) / 2 = (2n + 2) * (n - 1) / 2次操作,所以其时间复杂都为O(n2)。