插入排序也是一种非常容易理解的算法,核心思想就是每次将新的元素往原本有序的数组中插入。
算法思路
假设有下面一组数据,需要从小到大升序排列。
插入排序的算法是
1. 进行多轮迭代。
2. 每一次迭代的前提是将当前的数值插入到前面已经排序好的子数组当中。
也许描述有写抽象,但用显示当中玩扑克牌的经验可以很好地类比插入排序。
比如你手里已经有一堆牌。
5、6、J、K
如果你再抓到一张 9,那么你会怎么安放呢?
你一定会插入到 6 与 J 之间
5、6、<- 9 -> 、J、K
现在,整个牌面仍然是有序的,以后的操作都是如此的。
那么,实际上用插入排序时,我们应当将一个数组从左到右切割成有限个有序子数组,然后重复应用插入排序的逻辑直到结束。
图例示意:
Python 代码演示:
def insert_sort(srcArr):
size = len(srcArr)
for i in range(1,size):
key = srcArr[i];
j = i -1;
while key < srcArr[j] and j >= 0:
srcArr[j+1] = srcArr[j]
j -= 1
srcArr[j+1] = key
return srcArr
if __name__ == "__main__":
arr = [3,2,8,4,1,6,5]
print("=======================")
print(arr)
result = insert_sort(arr)
print("=======================")
print(result)
运行结果如下:
=======================
[3, 2, 8, 4, 1, 6, 5]
=======================
[1, 2, 3, 4, 5, 6, 8]
可以看到,排序结果正确。
上面的代码很简单,稍微难于理解的可能是 while 循环体中的那一段。
其实,插入排序能够插入,后面的数组都需要向后挪一个位置。
用 C++ 很容易用链表实现这个操作,断开链接,再接上新的值的链接就好了。
而在 Python 中,需要给 List 中的数字提前挪窝,所以最后给指定位置赋值,就相当于插入了一样。
时间复杂度
用大 O 表示法,选择排序的时间复杂性度是 .
看看最坏的情况,如果一个数组完全逆序的话,每一次插入都要移动前面的元素,那么需要进行多少次移动呢?
1 + 2 + 3 + ... + n-1=(n^2)/2
用大O 计数法,省略常数项就是 。
最好的情况是什么呢?
那就是整个数组已经有序了,并不需要插入,保持现状就好了,时间复杂度就是