插入排序(Insertion Sort)的基本思想是:将列表分为2部分,左边为排序好的部分,右边为未排序的部分,循环整个列表,每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的子序列中的适当位置,直到全部记录插入完成为止。
插入排序非常类似于整扑克牌。
在开始摸牌时,左手是空的,牌面朝下放在桌上。接着,一次从桌上摸起一张牌,并将它插入到左手一把牌中的正确位置上。为了找到这张牌的正确位置,要将它与手中已有的牌从右到左地进行比较。无论什么时候,左手中的牌都是排好序的。
也许你没有意识到,但其实你的思考过程是这样的:现在抓到一张7,把它和手里的牌从右到左依次比较,7比10小,应该再往左插,7比5大,好,就插这里。为什么比较了10和5就可以确定7的位置?为什么不用再比较左边的4和2呢?因为这里有一个重要的前提:手里的牌已经是排好序的。现在我插了7之后,手里的牌仍然是排好序的,下次再抓到的牌还可以用这个方法插入。编程对一个数组进行插入排序也是同样道理,但和插入扑克牌有一点不同,不可能在两个相邻的存储单元之间再插入一个单元,因此要将插入点之后的数据依次往后移动一个单元。
def insertion_sort(array): for i in range(1,len(array)): position = i#大循环走到了第i+1个元素(默认从第2个元素开始) current_val = array[position] while position > 0 and current_val < array[position-1]:直到出现position为0或者当前位置左边的元素小于当前位置元素才跳出循环 array[position] = array[position-1]#如果左边的元素大于当前位置的元素,就把左边的值给当前位置 position -=1 else: array[position] = current_val array = [45,12,4,53,198,9,65] insertion_sort(array) print(array) #[4, 9, 12, 45, 53, 65, 198]
简单容易理解的版本:
data_set = [45,12,4,53,198,9,65] for i in range(len(data_set)):#从第二个数开始,依次对前2个,3个。。。进行排序,相当于每次把第i+1个数插进去,和前面已经排序好的数作比较 while i > 0 and data_set[i] < data_set[i-1]: data_set[i],data_set[i-1] = data_set[i-1],data_set[i] i -= 1 print(data_set) #[4, 9, 12, 45, 53, 65, 198]
如果碰见一个和插入元素相等的,那么插入元素把想插入的元素放在相等元素的后面。所以,相等元素的前后顺序没有改变,从原无序序列出去的顺序就是排好序后的顺序,所以插入排序是稳定的。
直接插入排序复杂度:
时间复杂度: 最好情况O(n), 最坏情况O(n^2), 平均情况O(n^2)
空间复杂度: O(1)
稳定性: 稳定