原理
插入排序实际上跟我们打牌一样,斗地主应该大部分人都会玩的,我们在抓牌的时候,每当从下面抓起一张牌,我们就会将这张牌放到合适的位置,使手上的牌始终是一个有序的状态(有些人打牌也习惯乱放,前提是自己看得懂)。那么插入排序的过程,和以上的过程就很相似。
插入排序,首先将数列分成两部分,将数列的第一个数划分为left部分,剩下的数为right部分,我们依次将right部分的数一个一个取出,然后将该数放入left部分合适的位置,这样,left部分数越来越多,right部分的数越来越少,最后right部分为空,这时候left部分就为有序数列了。
核心实现代码为:
for right in range(1:len(iList))#从第二个元素开始遍历right部分
target=iList[right]#将每一个遍历的元素赋值为target
for left in range(0:right)#遍历left部分(left部分有序)
if target<=iList[left]:#找到target该插入的位置
iList[left+1:right+1]=iList[left:right]#插入位置后元素整体后移一位
iList[left]=target#将target放在合适位置
我们还是那个例子:
1.第一轮排序
我们将数列分为left和right两部分。开始的时候left部分为第一个数7(有序部分),剩下的为right部分(待排序部分)。
2.第二轮排序
从right中取出第一个数字3,然后将它放入left中合适的位置。从前往后遍历left部分的数,发现7比3大,然后将7以及后面的数(当前情况7后面没有数字)往后移一位,将3放在原本7所在的位置。(这里因为left只有一个7,比较简单,但是不了left部分多长都是一样的思想)
3.第三轮排序
我们从right部分继续选出元素5,然后从头遍历left部分的数,发现数字7比5大,这时候将7以及7后面的元素(当前情况7后面没有数字)往后移一位,将3放在原本7在的位置。
4.第四轮排序
5.第五轮排序
6.第六轮排序
自此,left部分为原数列排序后的有序数列。
代码实现
from randomList import randomList#这个模块是自定义的,在“Leetcode-排序-冒泡排序”那篇文章
import timeit
iList = randomList(20)
def insertionSort(iList):
if len(iList) <= 1:
return iList
for right in range(1, len(iList)):
target = iList[right]
for left in range(0, right):
if target <= iList[left]:
iList[left + 1:right + 1] = iList[left:right]
iList[left] = target
break
return iList
if __name__ == '__main__':
print(iList)
print(insertionSort(iList))
print(timeit.timeit("insertionSort(iList)", "from __main__ import insertionSort,iList", number=100) ) # 用这个算法排序100次所花时间
整理于2020年10月16日