插入排序是一种简单且经典的排序算法,其基本思想是通过将未排序的元素逐个插入到已排序的子数组中来实现整个数组的排序。该算法的时间复杂度为 O(n2)O(n2),适用于小型数据集,并且在某些情况下可以达到 O(n)O(n) 的时间复杂度。
插入排序的基本步骤
- 初始化:假设第一个元素已经排好序。
- 遍历数组:从第二个元素开始,逐个处理每个元素。
- 插入元素:对于每个未排序的元素,将其与前面已排序的部分进行比较,找到合适的位置并插入。
具体实现如下:
public class InsertionSort {
public static void insertionSort(int[] arr) {
if (arr == null || arr.length <= 1) {
return;
}
for (int i = 1; i < arr.length ; i++) {
int key = arr[i];
int j = i - 1;
// 将大于key的元素向右移动
while (j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j];
j--;
}
// 插入key到正确位置
arr[j + 1] = key;
}
}
public static void main(String[] args) {
int[] arr = {9, 5, 1, 4, 3};
insertionSort(arr);
for (int num : arr) {
System.out.print (num + " ");
}
}
}
算法原理详解
插入排序的核心在于不断将一个值插入到已排序的子序列中。例如,对于一个初始未排序的数组,我们首先将第一个元素视为已排序部分,然后将第二个元素插入到第一个元素之前或之后,使其成为有序序列的一部分。这个过程会重复进行,直到所有元素都被插入到已排序的子序列中。
在每次插入操作中,需要比较当前待插入元素与已排序部分的元素,如果当前元素小于已排序部分的某个元素,则向前移动该元素,直到找到合适的位置为止。这一过程可以通过以下伪代码表示:
for (int i = 1; i < list.length ; i++) {
int currentElement = list[i];
int j = i - 1;
// 找到插入位置
while (j >= 0 && list[j] > currentElement) {
list[j + 1] = list[j];
j--;
}
// 插入元素
list[j + 1] = currentElement;
}
性能分析
插入排序的时间复杂度为 O(n2)O(n2),其中 nn 是数组的长度。尽管在最佳情况下(即输入数组已经是有序的情况下),其时间复杂度可以降低到 O(n)O(n)。然而,在最坏的情况下(即输入数组完全逆序的情况),其时间复杂度仍然是 O(n2)O(n2)。
空间复杂度方面,插入排序只需要常数级别的额外空间,因此是一个稳定的排序算法。
实际应用
插入排序由于其实现简单和较低的空间复杂度,在小型数据集上表现较好。此外,它还可以作为其他更复杂排序算法的基础部分,如归并排序中的合并步骤。
总之,插入排序是一种基础而有效的排序方法,适合初学者理解和掌握基本的排序概念和算法思想。