介绍
直接插入排序(Straight Insertion Sort)是一种最简单的排序方法,其基本操作是将一条记录插入到已排好的有序表中,从而得到一个新的、记录数量增1的有序表。
用法与要点
先将序列的第1个记录看成是一个有序的子序列,然后从第2个记录逐个进行插入,直至整个序列有序为止。
要点:
- 设立哨兵,作为临时存储和判断数组边界之用。
- 如果碰见一个和插入元素相等的,那么插入元素把想插入的元素放在相等元素的后面。所以,相等元素的前后顺序没有改变,从原无序序列出去的顺序就是排好序后的顺序,所以插入排序是稳定的。
代码实例
先看看我自己写的,比较简单易懂一些
public static int[] arr = new int[] { 67, 88, 90, 17, 69, 20, 77, 42, 16, 12, 17 };
public static void InsertSort()
{
for (int i = 1; i < arr.Length; i++)
{
// 碰到临近的上一个下标的数值比当前下标的数值大的,进行调换位置
if (arr[i-1] > arr[i])
{
int j = 0;
// 默认是i下标之前的都是排序好的
for (j = i-1; j >= 0; j--)
{
// 如果排序好的序列中的数值比当前下标的数值还要大,就行换位置
if (arr[j] > arr[i])
{
int temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
}
// 换完位置,记得之前排序好的序列需要重新排序
if(j > 0 && arr[j] < arr[j-1])
{
int temp2 = arr[j - 1];
arr[j - 1] = arr[j];
arr[j] = temp2;
}
}
}
}
}
再看看大佬写的,大家可以对比一下,看看大佬的代码优势在哪里!尽量向大佬学习。
// 遍历array数组
// 为什么要从1开始,因为假设0坐标这部分是已经排序好的,从小到大排序好的,
// 先将序列的第1个记录看成是一个有序的子序列
for (int i = 1; i < array.Length; i++)
{
// 如果i-1坐标的值,大于i坐标的值
if (array[i] < array[i-1])
{
// 使用temp临时变量存储array[i]的数值
int temp = array[i];
// 标记,哨兵
int j = 0;
// 从i开始递减遍历,因为确定i前面都是从小到大排序好的(有序数组)
// 当i等于1的时候,j >= 0其实是为了防止数组溢出,因为arry[-1]为空,会报错
// (temp<array[j])其实就是(array[i]<array[i-1]),因为temp是array[i],而j = i-1,就是array[i-1]
for (j = i-1; j >= 0 && temp < array[j]; j--)
{
// j + 1永远等于i,所以这里其实是把array[i]变成了array[i-1]
// 因为实际情况是array[i]的值是比array[i-1]的值小
array[j + 1] = array[j];
}
// 这时候,遇到了j越界,或者小坐标的值大于后坐标的值
// 这时候j基本上等于i-1-1,也就是j+1=i-1。
// 说到最后还是间接的实现了,两个数的交换
array[j + 1] = temp;
}
}
看到这里,作者突然理解了。什么是插入排序,插入排序的本质就是直接插入,而上面插入排序的精髓点就是如下代码:
for (j = i-1; j >= 0 && temp < array[j]; j--)
{
// 将比temp大的数集体往后移动
array[j + 1] = array[j];
}
// 最后找到比temp小的数,然后往这个数的后面一个下标插入temp数
array[j + 1] = temp;
这两句就是整个排序插入的精髓所在
算法复杂度分析
从两串代码的的算法来看。时间复杂度基本上都是O(n²),为什么,因为两个遍历都是跟数组的长度也就是相当于n有关,空间复杂度都是O(1),因为遍历循环的时候,没必要使用数组来存储。这只是大致上来说的,如果真的要说的严谨一点。那么我们继续分析一下。
假设,一行代码就运行1秒,排除大括号,每个遍历都假设成需要遍历n次,那么我的第一行就会运行1秒,然后后面到第二个for循环之前都是需要运行n次的,迄今为止也就是n+n+1秒,第二个for循环代码又运行n秒,那就是3n+1秒,第二个for循环里面是需要走n*n次的,也就是最坏的情况是8n²,那么最后结果是3n+1+8n²秒。
同理可得,大神的代码最坏是需要4n+n²+1秒的,所以还是大神的代码写的完美,优化的比较彻底。大神的代码来自这里:
点击跳转查看