开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 26 天,点击查看活动详情
认识排序
排序就是将数据按一定顺序重新排列,即将数据按照键重新排列为升序( 从小到大 ) 或降序( 从大到小 ) 的处理。
比如:
- 一个数列为:
A = {5, 1, 3, 4, 2}
- 按升序排列:
A = {1, 2, 3, 4, 5}
- 按降序排列:
A = {5, 4, 3, 2, 1}
我们通过数组来管理这些数列形式的数据,并通过循环处理完成数据的交换和移动,最终实现排序。
我们在设计或者选择算法时,不仅需要考虑复杂度,还要考虑该排序算法是否稳定。
稳定排序指的是:当需要排序的数据中存在 2 个或者 2 个以上的相等值时,这些元素在排序前后的顺序不变。
插入排序 | Insertion Sort
思想
举个例子,比如我们拿着手牌在打扑克,需要将牌从左到右,由小到大进行排序。此时我们需要将牌一张张抽出来,分别插入到前面已排好序的手牌中的适当位置。重复这一操作 直到插入最后一张牌,整个排序就完成了。
插入排序就是这样一个思想。
具体的,插入排序算法记录如下:
-
首先,插入排序算法将开头元素视为已排序完成
-
接着执行以下处理(直到排序完成):
- 取出未排序部分的开头元素赋给变量
tmp
- 在已排序部分,将所有比
tmp
大的元素向后移动一个单位 - 将已取出的元素
tmp
插入空位 - 重复以上流程,直到排序结束
- 取出未排序部分的开头元素赋给变量
代码
插入算法的代码如下:(C++版):
// 包含了 n 个元素的数组 A
void insertionSort(int A[], int n) {
int i, j, tmp;
for(i = 1; i < n; i++) {
tmp = A[i];
j = i - 1;
while( j >= 0 && tmp < A[j] ) {
A[j+1] = A[j];
j--;
}
A[j+1] = tmp;
}
}
插入排序在整个排序过程中,会将数组分为两个部分:已排序部分 和 未排序部分。
在上述 C++ 代码中可以看到:
- 外层循环的
i
从 1 开始自增。在每次循环开始时,将A[i]
的值临时保存在变量tmp
中,tmp
变量的值就是未排序部分的开头元素。 - 接着是内部循环。我们要从前面已排序部分中,挨个寻找。将每个比
tmp
大的元素都后移一位,此时一旦遇到一个值比tmp
小,那么就将tmp
存放到该值的后面。 - 重复以上过程,就能成功排序完毕。
因此,我们说插入排序算法最核心的操作就是:将已排序部分的其中一段向后移动,再把未排序部分的开头元素插入已排序部分的恰当位置。
分析
在插入排序法中:
- 稳定性:我们只将比
tmp
大的元素向后移动,不相邻的元素不会直接交换位置,因此整个排序算法十分稳定。 - 时间复杂度:
记录:
- 插入排序算法的优势在于能够快速处理相对有序的数据。