排序算法笔记—基于Python

参考

中国大学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。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值