插入排序过程详解
1,引入
-
插入排序是一个笼统的叫法,那些使用插入思路进行排序的算法都可以叫插入排序。
-
这篇文章介绍其中最基础的一种——直接插入排序。
-
直接插入排序虽然简单,但它包含插入排序这类算法的基本思路,对掌握其它复杂一点的插入排序算法很有帮助。
2,外层取元素,内层找位置
- 如果下面实现部分的代码读不懂,请回来再多看几遍这个标题😎
- 写大纲的时候,我用的标题是
外层选元素,内层找位置
,如果用选
可能会越俎代庖(选择排序💢),所以这里取
表示的是当前从左到右遍历到哪个元素便插入哪个元素。 - 直接插入排序的思路:给我们一组待排序的数,从左到右,先把第一个元素看成一组已经有序的数(一个元素自己自然有序),取第二个元素插到这组已经有序的数中,插入后使这组数仍然有序。然后再取第三个元素往这组仍然有序的数中插…直到把第
n
个元素插入到前n-1
个有序的数中(n
是元素个数)排序就完成了。 - 有个问题:把一个数插入到一个已经有序的一组数中,让插入后的这组数仍然有序。不能随便找个位置插入,直接插入排序的做法很笨:拿这个待插入的数与组里的数挨个比较,直到找到一个不大于自己的(升序排序),然后就把自己安排在这个数后面。(如你所料,二分插入排序只是在找这个位置的时候使用了二分查找 !)
- 文字说的啰嗦,看看图解:
- 给定待升序序列
0 5 3 2 4 7
- 第一步,我们把
0
看成自己的有序序列,将5插入,因为只有0
一个元素,所以只比较一次就能确定应该插入的位置:
- 结果是什么也没发生,和起始数列一样,
5
仍然跟在0
的后面。 - 我们再尝试一步:
- 现在,在我们前一步形成的有序序列(
0 5
)中插入下一个元素(3
),按照挨个比较的原则,3
和5
比较,小于关系,所以3
至少应该排在5
前面,这个时候我们把5
往后移动一个:
3
继续和0
比较,大于关系,这时我们知道3
应该在0
的后面,所以3
的位置也就确定了,于是得到一个新的有序序列和待插入元素:
- 这里有个实现层面的问题:
将
5
往后移动,程序里是赋值,现在处于这个位置的元素,也就是我们即将要插入的元素3
的确被覆盖了,但是我们会用一个变量来记住我们当前待插入的元素。所以3
不会丢失。上图中之所以用空来填充是方便理解,表示我们并不关心这里面的值,因为它们随时可能被其它值覆盖。下面这幅图可能更准确: