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处理XML文件的方法
Aug 31 Python
Python常用库推荐
Dec 04 Python
Python实现的基数排序算法原理与用法实例分析
Nov 23 Python
python3.6利用pyinstall打包py为exe的操作实例
Oct 31 Python
Python3获取电脑IP、主机名、Mac地址的方法示例
Apr 11 Python
使用pycharm在本地开发并实时同步到服务器
Aug 02 Python
python字典的遍历3种方法详解
Aug 10 Python
Python 实现一个手机号码获取妹子名字的功能
Sep 25 Python
基于python修改srt字幕的时间轴
Feb 03 Python
解决pyinstaller打包运行程序时出现缺少plotly库问题
Jun 02 Python
python通用数据库操作工具 pydbclib的使用简介
Dec 21 Python
Python djanjo之csrf防跨站攻击实验过程
May 14 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 Global变量定义当前页面的全局变量实现探讨
2013/06/05 PHP
Ajax提交表单时验证码自动验证 php后端验证码检测
2016/07/20 PHP
PHP实现清除MySQL死连接的方法
2016/07/23 PHP
关于Curl在Swoole协程中的解决方案详析
2019/09/12 PHP
JS 实现图片直接下载示例代码
2013/07/22 Javascript
Javascript判断图片尺寸大小实例分析
2014/06/16 Javascript
jQuery实现ichat在线客服插件
2014/12/29 Javascript
Javascript闭包(Closure)详解
2015/05/05 Javascript
高性能JavaScript 重排与重绘(2)
2015/08/11 Javascript
只需五句话搞定JavaScript作用域(经典)
2016/07/26 Javascript
Jquery删除css属性的简单方法
2016/12/04 Javascript
获取JavaScript异步函数的返回值
2016/12/21 Javascript
ES6概念 Symbol.keyFor()方法
2016/12/25 Javascript
微信小程序 解决swiper不显示图片的方法
2017/01/04 Javascript
微信小程序上滑加载下拉刷新(onscrollLower)分批加载数据(二)
2017/05/11 Javascript
基于vue-ssr服务端渲染入门详解
2018/01/08 Javascript
在axios中使用params传参的时候传入数组的方法
2018/09/25 Javascript
JavaScript canvas绘制折线图
2020/02/18 Javascript
通过实例了解Javascript柯里化流程
2020/03/03 Javascript
vue实现图片上传功能
2020/05/28 Javascript
vue 授权获取微信openId操作
2020/11/13 Javascript
[04:07]显微镜下的DOTA2第八期——英雄复活动作
2014/06/24 DOTA
[01:12](回顾)DOTA2国际邀请赛,全世界DOTAer的盛宴
2014/07/01 DOTA
Python实现提取谷歌音乐搜索结果的方法
2015/07/10 Python
Python标准库06之子进程 (subprocess包) 详解
2016/12/07 Python
Python  pip安装lxml出错的问题解决办法
2017/02/10 Python
Python实现在线音乐播放器
2017/03/03 Python
Django项目基础配置和基本使用过程解析
2019/11/25 Python
基于python实现判断字符串是否数字算法
2020/07/10 Python
经典演讲稿范文
2013/12/30 职场文书
市场营销专业求职信
2014/06/17 职场文书
2015年医生个人工作总结
2015/04/25 职场文书
调解协议书范本
2016/03/21 职场文书
详解MySQL多版本并发控制机制(MVCC)源码
2021/06/23 MySQL
Python Matplotlib绘制动画的代码详解
2022/05/30 Python
3050和2060哪个好 性能差多少 差距有多大 谁更有性价比
2022/06/17 数码科技