python 排序算法 简书_排序算法总结与 Py 实现

排序算法总结与 Py 实现

这篇文章主要借鉴了地址,原文是 Java 实现的,质量特别棒。

算法分类:

常见排序算法一般分为两大类:

比较型排序:通过比较决定元素的相对次序,由于其时间复杂度不能突破O(nlogn),因此也称为非线性时间比较类排序。

非比较排序::不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时间下界,以线性时间运行,因此也称为线性时间非比较类排序。

排序算法.png

算法复杂度

算法复杂度.png

相关概念

稳定:即元素的相对顺序是否会发生改变,如 a 原本在 b 前面,而 a=b,排序之后 a 仍然在 b 的前面,则算法是稳定的。有些算法由于判断条件是 >= 或 <= ,这个条件包含了相等的状态,这会导致该元素会落在最后的位置。

不稳定:如果a原本在b的前面,而a=b,排序之后 a 可能会出现在 b 的后面。有些算法由于判断条件是 >= 或 <= ,这个条件包含了相等的状态,这会导致该元素会落在最后的位置。

稳定举例:比如你考试成绩一直和班里的另一个同学相同,那么稳定的排序算法就是每次总排名你都在他前头,而不是这次他排你前头,下次你排他前头。

时间复杂度:对排序数据的总的操作次数。

空间复杂度:是指算法在计算机

内执行时所需存储空间的度量,它也是数据规模n的函数。

1、冒泡排序

冒泡排序是一种遍历的排序算法。它重复地走过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。每次遍历都会把一个值放到合适的位置。

1.1 算法描述

比较相邻的元素。如果第一个比第二个大,就交换它们两个;

对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;

针对所有的元素重复以上的步骤,除了最后一个;

重复步骤1~3,直到排序完成。

1.2 图示

冒泡.png

冒泡.png

1.3 代码

def mao(nums):

n = len(nums)

for i in range(n):

# n个数,遍历 n 次

for j in range(n-i-1):

# 因为每次遍历都会放一个数到合适的位置,所以 - i,

# 又因为是在比较 nums[j] 与 nums[j+1],j+1的操作可以帮住我们上扩大遍历的范围,所以 - 1

if nums[j] > nums[j+1]:

# 注意这里是 > 号,所以不会交换相同的值,所以冒泡是稳定的算法

nums[j], nums[j+1] = nums[j+1], nums[j]

print(nums)

return nums

2、快速排序

快速排序的基本思想:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。

2.1 算法描述

快速排序使用分治法来把一个串(list)分为两个子串(sub-lists)。具体算法描述如下:

从数列中挑出一个元素,称为 “基准”(pivot);

重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;

递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

2.2 图示

快速排序.png

代码

def quick(nums, left, right):

if left < right:

i, j = left, right

i 是左指针,j 是右指针

base = nums[i]

#使用待排序列的第一个数做作为基数

print(base)

while i < j:

while i < j and nums[j] >= base:

# j 会 pass 过所有大于等于 base 的值。注意这里也会 pass 过相等的值,这使得快速不是稳定的算法

j -= 1

# 使 j 指针停在小于基数的位数

nums[i] = nums[j]

# 把 nums[j]的值 移到 i 的位置(让小的数把前头的值占了。)

while i < j and nums[i] <= base:

i += 1

# 使 j 指针停在大于基数的位数

nums[j] = nums[i]

# 把 nums[i]的值 移到 j 的位置(让大的数把后头的值占了。)

nums[i] = base

# 在最后 i 会停在合适的位置,(左小右大),其实每次quick都只能保证一个数字排到合适的位置。

print(i)

# 使用递归把剩下的数列排序了

quick(nums, left, i-1)

quick(nums, i+1, right)

return nums

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值