插入排序 Insertion Sort
插入排序的工作方式和对扑克牌的排序非常类似。想象一下打扑克牌时抽牌的过程。一开始我们手中没有牌。当从牌堆中拿到第一张牌时可直接放入手中。当从牌堆中拿到第二张牌时,我们会将它与第一张牌比较,放入合适的位置以维持手中的牌有序,之后依此类推。
和选择排序的区别:
选择排序是首先在无序表中找到最小值,放到有序表的最后一位
插入排序是将无序列表的第一位取出,排序后放入有序列表中
实现:
首先将原列表的第一位当作有序列的第一位,然后从原列表的第二位开始,将第二位和有序列表中的每个元素依次比较,找到合适的位置后,将其后面的元素后移,然后将第二位插入。重复上述步骤直到无序列表没有元素剩余
// java
public static void insertionSort(int[] arr) {
for (int i=1; i<arr.length; i++) {
int val = arr[i];
int pos = i-1;
// 排序
while(pos >= 0 && val < arr[pos]) {
// 将比val大的元素向后移动
arr[pos+1] = arr[pos];
pos--;
}
//当退出while循环时,pos就是正确位置的前一位
arr[pos+1] = val;
}
// 打印
for (int i=0; i<arr.length; i++) {
System.out.println(arr[i]);
}
// C++
void insertionSort(vector<int> &nums) {
for (int j=1;j<nums.size();j++) {
int key = nums[j];
int i = j-1;
while (i>=0 && nums[i]>key) {
nums[i+1] = nums[i];
i--;
}
nums[i+1] = key;
}
}
时间复杂度:
平均时间复杂度: T ( n ) = 1 + 2 + ⋯ + n − 2 + n − 1 = n ( n − 1 ) 2 = O ( n 2 ) T(n) = 1 + 2 + \dots + n-2 + n-1 = \frac{n(n-1)}{2} = O(n^2) T(n)=1+2+⋯+n−2+n−1=2n(n−1)=O(n2)
最优时间复杂度:列表正序时,情况最优,但仍需要从第一个元素循环到最后一个元素,因此 T ( n ) = O ( n ) T(n) = O(n) T(n)=O(n)
最坏时间复杂度:列表倒序时,情况最坏,不仅需要从第一个元素遍历到最后一个元素,在排序时也需要遍历有序列表的所有元素,因此
T
(
n
)
=
O
(
n
2
)
T(n) = O(n^2)
T(n)=O(n2)
空间复杂度:
由于只用到了常数个临时变量,所以空间复杂度为
O
(
1
)
O(1)
O(1)
稳定性:
插入排序可以选择不改变等值元素的顺序,因此插入排序是稳定的
总结:
对少量元素或是整体已基本有序的数列,插入排序有着比较优秀的性能。
相关章节
第一节 简述
第二节 稀疏数组 Sparse Array
第三节 队列 Queue
第四节 单链表 Single Linked List
第五节 双向链表 Double Linked List
第六节 单向环形链表 Circular Linked List
第七节 栈 Stack
第八节 递归 Recursion
第九节 时间复杂度 Time Complexity
第十节 排序算法 Sort Algorithm
第十一节 冒泡排序 Bubble Sort
第十二节 选择排序 Select Sort
插入排序 Insertion Sort
第十四节 冒泡排序,选择排序和插入排序的总结
第十五节 希尔排序 Shell’s Sort
第十六节 快速排序 Quick Sort
第十七节 归并排序 Merge Sort