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 流程控制实例代码
Sep 25 Python
深入浅析python中的多进程、多线程、协程
Jun 22 Python
python 简单搭建阻塞式单进程,多进程,多线程服务的实例
Nov 01 Python
Python面向对象之继承代码详解
Jan 29 Python
Python sklearn KFold 生成交叉验证数据集的方法
Dec 11 Python
使用Python和Prometheus跟踪天气的使用方法
May 06 Python
Python爬虫运用正则表达式的方法和优缺点
Aug 25 Python
Windows下Pycharm远程连接虚拟机中Centos下的Python环境(图文教程详解)
Mar 19 Python
Django admin 实现search_fields精确查询实例
Mar 30 Python
python使用Thread的setDaemon启动后台线程教程
Apr 25 Python
Django实现微信小程序支付的示例代码
Sep 03 Python
python tqdm用法及实例详解
Jun 16 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
phpMyAdmin 安装及问题总结
2009/05/28 PHP
PHP利用header跳转失效的解决方法
2014/10/24 PHP
PHP文件管理之实现网盘及压缩包的功能操作
2017/09/20 PHP
php写入文件不覆盖的实例讲解
2019/09/17 PHP
PHP日期和时间函数的使用示例详解
2020/08/06 PHP
浅析jQuery1.8的几个小变化
2013/12/10 Javascript
ListBox实现上移,下移,左移,右移的简单实例
2014/02/13 Javascript
jquery获取元素索引值index()示例
2014/02/13 Javascript
AngularJS的一些基本样式初窥
2015/07/27 Javascript
jQuery带进度条全屏图片轮播特效代码分享
2020/06/28 Javascript
js滚动条平滑移动示例代码
2016/03/29 Javascript
jQuery插件cxSelect多级联动下拉菜单实例解析
2016/06/24 Javascript
Vue组件BootPage实现简单的分页功能
2016/09/12 Javascript
angular中的http拦截器Interceptors的实现
2017/02/21 Javascript
jQuery表单设置值的方法
2017/06/30 jQuery
JS中Safari浏览器中的Date
2017/07/17 Javascript
JS实现图片手风琴效果
2020/04/17 Javascript
Vue+axios+WebApi+NPOI导出Excel文件实例方法
2019/06/05 Javascript
VUE:vuex 用户登录信息的数据写入与获取方式
2019/11/11 Javascript
vue从零实现一个消息通知组件的方法详解
2020/03/16 Javascript
利用vue3+ts实现管理后台(增删改查)
2020/10/30 Javascript
详尽讲述用Python的Django框架测试驱动开发的教程
2015/04/22 Python
详解Python实现按任意键继续/退出的功能
2016/08/19 Python
python中不能连接超时的问题及解决方法
2018/06/10 Python
Python在for循环中更改list值的方法【推荐】
2018/08/17 Python
使用 Visual Studio Code(VSCode)搭建简单的Python+Django开发环境的方法步骤
2018/12/17 Python
python3的UnicodeDecodeError解决方法
2019/12/20 Python
有趣的Python图片制作之如何用QQ好友头像拼接出里昂
2020/04/22 Python
python爬取抖音视频的实例分析
2021/01/19 Python
乡镇交通安全实施方案
2014/03/29 职场文书
法定代表人授权委托书格式
2014/10/14 职场文书
2014年幼儿园小班工作总结
2014/12/04 职场文书
2014年数学教研组工作总结
2014/12/06 职场文书
2014年煤矿工人工作总结
2014/12/08 职场文书
谢师宴邀请函
2015/02/02 职场文书
启迪人心的励志语录:脾气永远不要大于本事
2020/01/02 职场文书