参考
中国大学MOOC慕课—数据结构与算法Python版
力扣leetcode
CSDN博客
简书
插入排序
插入排序可以分为直接插入排序与分组插入排序(希尔排序)。直接插入排序的思想类似于整理扑克牌。当我们拿到一副牌的时候,我们希望由小到大进行排序,一般我们会选择小的牌插入到大的牌后面完成排序。当然这个过程十分感性,况且有我们强大的视觉功能,第一眼往往就能够识别出最大的牌和最小的牌。
而要让计算机完成这一操作,这个过程必须要被分为许多逻辑清晰有条有理的步骤。首先,我们将一副长度为n的无序表视为由长度为1的有序表和长度为n的无序表组成。即列表的第一个数处于有序表,其余n-1个数均处于无序表中。
接下来,我们要做的是把第二张牌取出,与第一张牌比较决定其插入位置。抽象出来就是,我们将第n张牌取出,与前面排好序的n-1张牌比较,直到某一张牌比第n张牌小为止。
在这个比较过程中,每一次比较都把前n-1张牌的位置往前移一位。即第一次就要把第n张牌的位置给占掉。因此我们首先就要把第n张牌的值记录到一个中间变量里面,且要把第n张牌的位置也要记录下来。
def insertsort(num):
for i in range(1,len(num)):
emptycup=num[i]
position=i
while emptycup<num[position-1] and position>0:
print(num[i],emptycup)
num[position]=num[position-1]
position=position-1
num[position]=emptycup
return num
num=[int(x) for x in input().split()]
print(insertsort(num))
在编写代码中,很容易出现的错误是,吧while empty<写成while num[i]小于,后者实际上是错误的,因为emptycup的值是固定的,但是num[i]是有可能被覆盖的。此外position的用法也值得注意。
从算法中可以看出,算法的时间复杂度在O(n^2)数量级。
归并排序
归并即先分治再归并,对于一个长度为n的无序表,我们永远将其视为由左右两部分组成(递归的应用)直到列表长度为1为止。此时,按照递归的原理,基本结束条件之后开始回递。
这个时候,一个长度为n的无序表被分成许多个左右两部分。且每个左右两部分的最小部分均只有一个元素。因此我们只需要比较左右两部分谁大即可。类似于拉拉链,左边小于右边则从左边取出一个元素放入新的列表,反之则取右边放入这个列表。值得注意的是,左右两边的列表长度不一定相等。因此,当左边或者右边取空时,剩下的一边的元素必然是最大的(大于新列表的所有元素)直接用extend添加入新列表即可。
def merge(num):
if len(num)==1:
return num
else:
mid=len(num)//2
left=merge(num[:mid])# 对左边进行排序
right=merge(num[mid:])# 对右边进行排序
orders=[]# 新列表
while left and right:# 整合左右
if left[0]>right[0]:
orders.append(right.pop(0))
else:
orders.append(left.pop(0))
orders.extend(right if right else left)
return orders
注意在使用递归函数时候,一定要站在全局来看不能只看细节。一定要弄清楚递归函数的作用是什么,有无返回值,基本结束条件是什么。要是只看局部的话很容易混乱。当然能够很好地利用递归实际上很需要经验和对递归很好的理解。
这里归并的代码,我们参照了陈斌老师的课件比较Pythonic。其中while right and left即只要当right和left均不是空列表时。因为空列表等价于false。同理exten(right if right else left) 如果right是True即非空否则就left。