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 28 Python
使用py2exe在Windows下将Python程序转为exe文件
Mar 04 Python
浅谈python为什么不需要三目运算符和switch
Jun 17 Python
速记Python布尔值
Nov 09 Python
Python爬虫包BeautifulSoup学习实例(五)
Jun 17 Python
神经网络相关之基础概念的讲解
Dec 29 Python
Python爬虫实现爬取百度百科词条功能实例
Apr 05 Python
python3中eval函数用法使用简介
Aug 02 Python
python中树与树的表示知识点总结
Sep 14 Python
Python中使用gflags实例及原理解析
Dec 13 Python
pytorch中的上采样以及各种反操作,求逆操作详解
Jan 03 Python
Python如何实现定时器功能
May 28 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
虫族 Zerg 热键控制
2020/03/14 星际争霸
首页四格,首页五格For6.0(GBK)(UTF-8)[12种组合][9-18][版主安装测试通过]
2007/09/24 PHP
PHP中strncmp()函数比较两个字符串前2个字符是否相等的方法
2016/01/07 PHP
php实现文章置顶功能的方法
2016/10/20 PHP
PHP获取input输入框中的值去数据库比较显示出来
2016/11/16 PHP
Javascript中的常见排序算法
2007/03/27 Javascript
javascript 不间断的图片滚动并可点击
2010/01/15 Javascript
ASP.NET jQuery 实例2 (表单中使用回车在TextBox之间向下移动)
2012/01/13 Javascript
关于jquery input textare 事件绑定及用法学习
2013/04/03 Javascript
jquery中选择块并改变属性值的方法
2013/07/31 Javascript
javascript:window.open弹出窗口的位置问题
2014/03/18 Javascript
jquery数组过滤筛选方法grep()简介
2014/06/06 Javascript
javascript弹出拖动窗口
2015/08/11 Javascript
jquery+ajax实现直接提交表单实例分析
2016/06/17 Javascript
BootStrap的table表头固定tbody滚动的实例代码
2016/08/24 Javascript
vue-router权限控制(简单方式)
2018/10/29 Javascript
vue中tab选项卡的实现思路
2018/11/25 Javascript
Angular8引入百度Echarts进行图表分析的实现代码
2019/11/27 Javascript
JS实现动态无缝轮播
2020/01/11 Javascript
一个小示例告诉你Python语言的优雅之处
2014/07/04 Python
Python使用遗传算法解决最大流问题
2018/01/29 Python
Python退火算法在高次方程的应用
2018/07/26 Python
对python中url参数编码与解码的实例详解
2019/07/25 Python
Python DataFrame一列拆成多列以及一行拆成多行
2019/08/06 Python
python中的反斜杠问题深入讲解
2019/08/12 Python
python安装本地whl的实例步骤
2019/10/12 Python
Python turtle库的画笔控制说明
2020/06/28 Python
HTML5 Canvas自定义圆角矩形与虚线示例代码
2013/08/02 HTML / CSS
Gap加拿大官网:Gap Canada
2017/08/24 全球购物
简历自我评价怎么写好呢?
2014/01/04 职场文书
《彭德怀和他的大黑骡子》教学反思
2014/04/12 职场文书
远程网络教育毕业生自我鉴定
2014/04/14 职场文书
党员教师群众路线个人整改措施
2014/10/28 职场文书
认真学习保证书
2015/02/26 职场文书
研究生给导师的自荐信
2015/03/06 职场文书
学习党史心得体会2016
2016/01/23 职场文书