第1关:插入排序的实现
任务描述
本关任务:编写代码实现插入排序。
相关知识
为了完成本关任务,你需要掌握: 1.如何实现插入排序; 2.插入排序的算法分析。
插入排序
插入排序的主要思路是始终在列表的前部维持一个已排好序的子列表,并不断地将待排序的数据项插入到有序子列表中,使有序子列表逐渐扩大,直至所有数据项都插入有序子列表中。
我们认为只含有 1 个数据项的列表是已经排好的,刚开始有序子列表仅包含第 1 个数据项。对于具有 n 个数据项的列表,需要将第 1 个数据项后面的 n-1 个数据项都按次序插入到有序子列表中,因此总共需要进行 n-1 趟排序。
-
第 1 趟排序,将第 2 个数据项作为插入的“新项”与第 1 个数据项进行比较,找到插入到子列表的合适位置使得子列表仍然有序,这样已排序的子列表就包含了 2 个数据项;
-
第 2 趟排序,继续将第 3 个数据项与前 2 个数据项进行比较,并将比自身大的数据项依次向右移动,空出位置来,以便将第 3 个数据项插入到子列表中;
-
经过 n-1 趟比较和插入,子列表扩展到全表,排序完成。
图 1 展示了插入排序的过程,其中阴影部分为已排好序的子列表,由于该无序表中具有 9 个数据,因此需要进行 8 趟排序。
图1 插入排序
图 1 中插入排序的过程可描述为:
-
第 1 趟排序,最初有序子列表仅包含第 1 个数据项 54,将插入项 26 与 54 进行比较,26 小于 54,放置在 54 前,此时有序子列表已包含“26,54”两个数据项;
-
第 2 趟排序,将插入项 93 与有序子列表中的数据项比较,确定插入位置为 54 之后,此时有序子列表已包含“26,54,93”三个数据项;
-
第 3 趟排序,将插入项 17 与有序子列表中的数据项比较,确定插入位置为 26 之前,此时有序子列表已包含“17,26,54,93”四个数据项;
-
第 4 趟排序,将插入项 77 与有序子列表中的数据项比较,确定插入位置为 54 与 93 之间,此时有序子列表已包含“17,26,54,77,93”五个数据项;
-
第 5 趟排序,将插入项 31 与有序子列表中的数据项比较,确定插入位置为 26 与 54 之间,此时有序子列表已包含“17,26,31,54,77,93”六个数据项;
-
第 6 趟排序,将插入项 44 与有序子列表中的数据项比较,确定插入位置为 31 与 54 之间,此时有序子列表已包含“17,26,31,44,54,77,93”七个数据项;
-
第 7 趟排序,将插入项 55 与有序子列表中的数据项比较,确定插入位置为 54 与 77 之间,此时有序子列表已包含“17,26,31,44,54,55,77,93”八个数据项;
-
第 8 趟排序,将插入项 20 与有序子列表中的数据项比较,确定插入位置为 17 与 26 之间,此时有序子列表已包含“17,20,26,31,44,54,55,77,93”九个数据项,整个列表已有序,排序完成;
图 2 详细地展示了图 1 中第 5 趟排序的过程。
图2 插入排序的第 5 趟排序
第 5 趟排序前,已排好的子列表中包含“17,26,54,77,93”五个数据。为了将 31 插入该子表中,需要进行下列比较:
-
首先将 31 与子列表最后的 93 进行比较,31 比 93 小,93 向右移动一个位置;
-
然后将 31 与 77 进行比较,31 比 77 小,77 向右移动一个位置;
-
然后将 31 与 54 进行比较,31 比 54 小,54 向右移动一个位置;
-
然后将 31 与 26 进行比较,31 比 26 大,于是找到了 31 的插入位置,31 插入到 26 右边。此时就有了一个含 6 个数据项的有序子列表,第 5 趟排序完成。
比较时,我们把之前已经排好的子列表中比这个插入项大的向右边移动一个位置,当子列表中的某个数据项小于当前插入项,或者当前插入项已经和子列表的所有数据项都比较了时,就可以在此处放置当前插入项。
插入排序的算法分析
与冒泡排序、选择排序一样,插入排序的时间复杂度仍然是O(
,但其算法思路不同,插入排序的比较操作主要用来寻找“新项”的插入位置。)
-
最差的情况是每趟排序都与子列表中的所有项进行比较,总比对次数与冒泡排序相同,数量级仍是
O(
;)
-
最好的情况是列表已经有序,每趟排序仅需 1 次比较,总次数是
O(n)
。
编程要求
在右侧编辑器中的 Begin-End 区间补充代码,根据插入排序的算法思想完成insertionSort
方法,从而实现对无序表的排序。
测试说明
平台会对你编写的代码进行测试,比对你输出的数值与实际正确的数值,只有所有数据全部计算正确才能通过测试:
测试输入:
54,26,93,17,77,31,44,55,20
输入说明:输入为需要对其进行排序的无序表。
预期输出:
[17, 20, 26, 31, 44, 54, 55, 77, 93]
输出说明:输出的是对无序表进行插入排序后的结果,以列表的形式展现。
测试输入:
49,38,65,97,76,13,27,49
预期输出:
[13, 27, 38, 49, 49, 65, 76, 97]
开始你的任务吧,祝你成功!
'''请在Begin-End之间补充代码, 完成insertionSort函数'''
def insertionSort(alist):
for index in range(1,len(alist)): # 需要将第1个数据项后的n-1个数据项插入到有序子列表,循环n-1次
currentvalue = alist[index] # 当前的插入项
position = index
# 进行比较和移动
# ********** Begin ********** #
while position>0 and alist[position-1]>currentvalue:
alist[position]=alist[position-1]
position-=1
# ********** End ********** #
# 插入新项
alist[position]=currentvalue