算法------排序
插入排序
【百度百科】
插入排序,一般也被称为直接插入排序。对于少量元素的排序,它是一个有效的算法 。插入排序是一种最简单的排序方法,它的基本思想是将一个记录插入到已经排好序的有序表中,从而一个新的、记录数增1的有序表。在其实现过程使用双层循环,外层循环对除了第一个元素之外的所有元素,内层循环对当前元素前面有序表进行待插入位置查找,并进行移动 。
【通俗解释】
其实简单通俗的说就好比是你手中有一些扑克牌,且他们是有序的,然后你拿上另一张牌插入到已经拍好序的这些扑克牌中,这就是插入排序。
【动图演示】
Talk is cheap, show me the code ------Linus Torvalds
显而易见的我们根据对定义和动图的理解可以初步写出的代码如下:
// 默认升序排列
int InsertSort(int arr[], int n) {
//[1, n - 1] 从第二个数开始
for (int i = 1; i < n; i++) {
//[i, 0) 注意数组越界问题
for (int j = i; j > 0; j--) {
//compare swap
if (arr[j] < arr[j-1]) {
int temp = arr[j];
arr[j] = arr[j - 1];
arr[j - 1] = temp;
}
}
}
return 0;
}
但是我们自己可以用随机的数组测试一下,发现其效率并不高,于是我们想着对其进行优化,再次思考其插入过程,不难发现,数组在每一次排完序后,前面的已经有序了,再将其后面的一个和前面的一个进行比较即可,若不符合,就不需要再往前比较了(其实是一次剪枝的过程)
于是我们对代码进行修改如下:
// 默认升序排列
int InsertSort(int arr[], int n) {
//[1, n - 1] 从第二个数开始
for (int i = 1; i < n; i++) {
//[i, 0) 注意数组越界问题
for (int j = i; j > 0; j--) {
//compare swap
if (arr[j] < arr[j-1]) {
int temp = arr[j];
arr[j] = arr[j - 1];
arr[j - 1] = temp;
}
else {
break; // 改完后再测试可以发现效率显著提高
}
}
}
return 0;
}
既然已经优化到这了,那我们不妨再深入思考一下,我们对这个数进行插入排序,将其插入到数组的某一个位置,我们只需要对其进行移位操作,而不需要进行繁琐的交换
那么再次修改后的代码如下:
// 默认升序排列
int InsertSort(int arr[], int n) {
//[1, n - 1] 从第二个数开始
for (int i = 1; i < n; i++) {
//[i, 0) 注意数组越界问题
int temp = arr[i];
int j = i;
for (; j > 0; j--) {
//compare swap
if (arr[j - 1] > temp) {
arr[j] = arr[j - 1]; // 向后移位
}
else {
break;
}
}
arr[j] = temp;
}
return 0;
}