python 常见的排序算法实现汇总


Posted in Python onAugust 21, 2020

python 常见的排序算法实现汇总

排序分为两类,比较类排序和非比较类排序,比较类排序通过比较来决定元素间的相对次序,其时间复杂度不能突破O(nlogn);非比较类排序可以突破基于比较排序的时间下界,缺点就是一般只能用于整型相关的数据类型,需要辅助的额外空间。

要求能够手写时间复杂度位O(nlogn)的排序算法:快速排序、归并排序、堆排序

1.冒泡排序

思想:相邻的两个数字进行比较,大的向下沉,最后一个元素是最大的。列表右边先有序。

时间复杂度$O(n^2)$,原地排序,稳定的

def bubble_sort(li:list):
  for i in range(len(li)-1):
    for j in range(i + 1, len(li)):
      if li[i] > li[j]:
        li[i], li[j] = li[j], li[i]

2.选择排序

思想:首先找到最小元素,放到排序序列的起始位置,然后再从剩余元素中继续寻找最小元素,放到已排序序列的末尾,以此类推,直到所有元素均排序完毕。列表左边先有序。

时间复杂度$O(n^2)$,原地排序,不稳定

def select_sort(nums: list):
  for i in range(len(nums) - 1):
    min_index = i
    for j in range(i + 1, len(nums)):
      if nums[j] < nums[i]:
        min_index = j
    nums[i], nums[min_index] = nums[min_index], nums[i]

3.插入排序

思想:构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。列表左边先有序。

时间复杂度$O(n^2)$,原地排序,稳定

def insert_sort(nums: list):
  for i in range(len(nums)):
    current = nums[i]
    pre_index = i - 1
    while pre_index >= 0 and nums[pre_index] > current:
      nums[pre_index + 1] = nums[pre_index]
      pre_index -= 1
    nums[pre_index + 1] = current

4.希尔排序

思想:插入排序的改进版,又称缩小增量排序,将待排序的列表按下标的一定增量分组,每组分别进行直接插入排序,增量逐渐减小,直到为1,排序完成

时间复杂度$O(n^{1.5})$,原地排序,不稳定

def shell_sort(nums: list):
  gap = len(nums) >> 1
  while gap > 0:
    for i in range(gap, len(nums)):
      current = nums[i]
      pre_index = i - gap
      while pre_index >= 0 and nums[pre_index] > current:
        nums[pre_index + gap] = nums[pre_index]
        pre_index -= gap
      nums[pre_index + gap] = current
    gap >>= 1

5.快速排序

思想:递归,列表中取出第一个元素,作为标准,把比第一个元素小的都放在左侧,把比第一个元素大的都放在右侧,递归完成时就是排序结束的时候

时间复杂度$O(nlogn)$,空间复杂度$O(logn)$,不稳定

def quick_sort(li:list):
  if li == []:
    return []
  first = li[0]
  # 推导式实现
  left = quick_sort([l for l in li[1:] if l < first])
  right = quick_sort([r for r in li[1:] if r >= first])
  return left + [first] + right

6.归并排序

思想:分治算法,拆分成子序列,使用归并排序,将排序好的子序列合并成一个最终的排序序列。关键在于怎么合并:设定两个指针,最初位置分别为两个已经排序序列的起始位置,比较两个指针所指向的元素,选择相对小的元素放到合并空间,并将该指针移到下一位置,直到某一指针超出序列尾,将另一序列所剩下的所有元素直接复制到合并序列尾。

时间复杂度$O(nlogn)$,空间复杂度O(n),不稳定

二路归并

def merge_sort(nums: list):
  if len(nums) <= 1:
    return nums
  mid = len(nums) >> 1
  left = merge_sort(nums[:mid]) # 拆分子问题
  right = merge_sort(nums[mid:])

  def merge(left, right): # 如何归并
    res = []
    l, r = 0, 0
    while l < len(left) and r < len(right):
      if left[l] <= right[r]:
        res.append(left[l])
        l += 1
      else:
        res.append(right[r])
        r += 1
    res += left[l:]
    res += right[r:]
    return res

  return merge(left, right)

7.堆排序

思想:根节点最大,大顶堆,对应升序,根节点最小,小顶堆。

  • 构建大根堆,完全二叉树结构,初始无序
  • 最大堆调整,进行堆排序。将堆顶元素与最后一个元素交换,此时后面有序

时间复杂度$O(nlogn)$,原地排序,稳定

def heap_sort(nums: list):
  def heapify(parent_index, length, nums):
    temp = nums[parent_index] # 根节点的值
    chile_index = 2 * parent_index + 1 # 左节点,再加一为右节点
    while chile_index < length:
      if chile_index + 1 < length and nums[chile_index + 1] > nums[chile_index]:
        chile_index = chile_index + 1
      if temp > nums[chile_index]:
        break
      nums[parent_index] = nums[chile_index] # 使得根节点最大
      parent_index = chile_index
      chile_index = 2 * parent_index + 1
    nums[parent_index] = temp

  for i in range((len(nums) - 2) >> 1, -1, -1):
    heapify(i, len(nums), nums) # 1.建立大根堆
  for j in range(len(nums) - 1, 0, -1):
    nums[j], nums[0] = nums[0], nums[j]
    heapify(0, j, nums) # 2.堆排序,为升序
    
if __name__ == '__main__':
  nums = [89, 3, 3, 2, 5, 45, 33, 67] # [2, 3, 3, 5, 33, 45, 67, 89]
  heap_sort(nums)
  print(nums)

以上就是python 常见的排序算法实现汇总的详细内容,更多关于python 排序算法的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
python实现在目录中查找指定文件的方法
Nov 11 Python
Python使用random和tertools模块解一些经典概率问题
Jan 28 Python
python+selenium开发环境搭建图文教程
Aug 11 Python
Python基础教程之利用期物处理并发
Mar 29 Python
python对html过滤处理的方法
Oct 21 Python
python设置随机种子实例讲解
Sep 12 Python
Tensorflow累加的实现案例
Feb 05 Python
Scrapy框架实现的登录网站操作示例
Feb 06 Python
ubuntu16.04升级Python3.5到Python3.7的方法步骤
Aug 20 Python
python中round函数保留两位小数的方法
Dec 04 Python
python使用smtplib模块发送邮件
Dec 17 Python
ASP.NET Core中的配置详解
Feb 05 Python
Python制作数据预测集成工具(值得收藏)
Aug 21 #Python
简述 Python 的类和对象
Aug 21 #Python
DRF框架API版本管理实现方法解析
Aug 21 #Python
Django rest framework分页接口实现原理解析
Aug 21 #Python
Python -m参数原理及使用方法解析
Aug 21 #Python
python使用布隆过滤器的实现示例
Aug 20 #Python
QT5 Designer 打不开的问题及解决方法
Aug 20 #Python
You might like
深入解析PHP中SESSION反序列化机制
2017/03/01 PHP
[原创]PHP正则删除html代码中a标签并保留标签内容的方法
2017/05/23 PHP
PHP常用工具函数小结【移除XSS攻击、UTF8与GBK编码转换等】
2019/04/27 PHP
redis+php实现微博(二)发布与关注功能详解
2019/09/23 PHP
div+css布局的图片连续滚动js实现代码
2010/05/04 Javascript
asp.net+js 实现无刷新上传解析csv文件的代码
2010/05/17 Javascript
Notify - 基于jquery的消息通知插件
2011/10/18 Javascript
JS、CSS加载中的小问题探讨
2013/11/26 Javascript
jquery内置验证(validate)使用方法示例(表单验证)
2013/12/04 Javascript
js中判断对象是否为空的三种实现方法
2013/12/23 Javascript
JavaScript设计模式之外观模式介绍
2014/12/28 Javascript
javascript下拉框选项单击事件的例子分享
2015/03/04 Javascript
JQuery中DOM实现事件移除的方法
2015/06/13 Javascript
详解AngularJS中的表达式使用
2015/06/16 Javascript
javascript实现unicode与ASCII相互转换的方法
2015/12/10 Javascript
js倒计时简单实现方法
2015/12/17 Javascript
JS组件Bootstrap实现弹出框效果代码
2016/04/26 Javascript
JavaScript面试开发常用的知识点总结
2016/08/08 Javascript
easyUI实现(alert)提示框自动关闭的实例代码
2016/11/07 Javascript
移动端脚本框架Hammer.js
2016/12/15 Javascript
基于vue-cli vue-router搭建底部导航栏移动前端项目
2018/02/28 Javascript
JS数组去重常用方法实例小结【4种方法】
2018/05/28 Javascript
vue拖拽组件 vuedraggable API options实现盒子之间相互拖拽排序
2019/07/08 Javascript
Python读写文件方法总结
2015/06/09 Python
Python自动登录126邮箱的方法
2015/07/10 Python
pandas数值计算与排序方法
2018/04/12 Python
对python中使用requests模块参数编码的不同处理方法
2018/05/18 Python
python时间日期操作方法实例小结
2020/02/06 Python
Python re正则表达式元字符分组()用法分享
2020/02/10 Python
Feelunique德国官方网站:欧洲最大的在线美容零售商
2019/07/20 全球购物
EJB面试题
2015/07/28 面试题
办公文员的工作岗位职责
2013/11/12 职场文书
2014三八妇女节活动总结范文四篇
2014/03/09 职场文书
校长新学期致辞
2015/07/30 职场文书
Python使用mitmproxy工具监控手机 下载手机小视频
2022/04/18 Python
MySQL解决Navicat设置默认字符串时的报错问题
2022/06/16 MySQL