快速排序同样也是分治的思想,核心依然是分而治之,各个击破。

快速排序的思想是:找到一个数字x,对数组nums进行排序,使x左侧的数字都小于x,右侧的数字都大于x,然后对左侧和右侧重复同样的操作,直到所有的数字都已按序排列。

根据上面的思想,实现代码如下:

#QuickSort:used the divide and conquer idea to sort array
def QuickSort(nums:list,left:int,right:int) -> list:'''nums: disorderly arryleft,right: bounds of the array to be sorted'''if left >= right:return p = getIndex(nums,left,right)QuickSort(nums,left,p-1)QuickSort(nums,p+1,right)return numsdef swap(nums:list,i:int,j:int):temp = nums[i]nums[i] = nums[j]nums[j] = tempdef getIndex(nums:list,left:int,right:int) -> int:'''divide nums around x'''n = nums[left]i,j = left,rightwhile True:while i < right and nums[i] <= n:i += 1 while nums[j] > n:j -= 1if i >= j:breakelse:swap(nums,i,j)nums[left] = nums[j]nums[j] = nreturn j

快排的时间复杂度受到所选择数字的影响,最坏的情况是每次找到的数字x均为最大或者最小,使得划分后一侧有n-1个数字,这样是时间复杂度为n^2,如果每次找的数字x都为中值,那么时间复杂度nlogn,这是最好的情况,快速排序的平均时间复杂度可以证明为 nlogn

对于快排的时间复杂度比较依赖于选取元的问题,我们可以使用随机取元的方法(任取left,right内的一个元素) 或者 三者取中(取nums[left],nums[mid],nums[right]三者中的中间值)

随机取元即在确定x的时候,不再是x=nums[left],而是随机的从nums[left,right]中取一个元素作为x,即令x = random.choice(range(left,right+1)),那么利用原先的代码,我们只要增加一个RandomGetIndex函数即可,实现代码如下:

def RandomGetIndex(nums:list,left:int,right:int) -> int:temp = random.choice(range(left,right+1))swap(nums,left,temp)index = getIndex(nums,left,right)return index#我们递归函数的代码修改为如下
def QuickSort(nums:list,left:int,right:int) -> list:'''nums: disorderly arryleft,right: bounds of the array to be sorted'''if left >= right:return p = RandomGetIndex(nums,left,right)QuickSort(nums,left,p-1)QuickSort(nums,p+1,right)return nums

三者取中的思想是希望能选取一个比较中间的值,这样可以使时间复杂度,更加趋近于nlogn,一般三者取中的策略是选择nums[left],nums[mid],nums[right],三个数里面居中的那个数字作为x,那么同样只需要增加一个ThreeGetMid函数来挑选中间值,然后调用getIndex即可:

def ThreeGetMid(nums:list,left:int,right:int) -> int:mid = (left+right)//2mid_num = getMidNum(nums,left,mid,right)swap(nums,left,mid_num)index = getIndex(nums,left,right)return indexdef getMidNum(nums:list,left:int,mid:int,right:int) -> int:if nums[left] >= nums[mid] and nums[left] <= nums[right]:return leftif nums[left] >= nums[mid] and nums[left] >= nums[right]:return mid if nums[mid] >= nums[right] else rightif nums[left] <= nums[mid] and nums[left] >= nums[right]:return leftif nums[left] <= nums[mid] and nums[left] <= nums[right]:return mid if nums[mid] <= nums[right] else right#我们递归函数的代码修改为如下
def QuickSort(nums:list,left:int,right:int) -> list:'''nums: disorderly arryleft,right: bounds of the array to be sorted'''if left >= right:return p = ThreeGetMid(nums,left,right)QuickSort(nums,left,p-1)QuickSort(nums,p+1,right)return nums

在前面那篇递归算法笔记中曾经说过,递归调用是一个消耗堆栈空间的过程,那我们在进行递归调用的时候,可能就需要不得不考虑栈溢出的问题。

递归调用是一个重复自身的过程,那我们可以在程序中模拟一个堆栈,然后再使用for循环或者while循环完成其重复调用的部分,就可以将递归调用的算法,转换成非递归的实现。

那我们只需要将我们的递归函数QuickSort改写成,下面这样的代码:

#QuickSort_No_Stack
def QuickSort_No_Stack(nums:list,left:int,right:int) -> list:temp = [left,right]while temp:j = temp.pop()  # j = righti = temp.pop()  # i = leftindex = getIndex(nums,i,j)if i < index-1:   # 压入堆栈 注意左右边界的顺序temp.append(i)temp.append(index-1)if j > index+1:temp.append(index+1)temp.append(j)return nums

人生不易 且行且珍惜

机器学习初学者

黄海广博士创建的公众号,黄海广博士个人知乎粉丝21000+,github排名全球前120名(30000+)。本公众号致力于人工智能方向的科普性文章,为初学者提供学习路线和基础资料。原创作品有:吴恩达机器学习个人笔记、吴恩达深度学习笔记等。

往期精彩回顾

  • 那些年做的学术公益-你不是一个人在战斗

  • 良心推荐:机器学习入门资料汇总及学习建议

  • 吴恩达机器学习课程笔记及资源(github标星12000+,提供百度云镜像)

  • 吴恩达深度学习笔记及视频等资源(github标星8500+,提供百度云镜像)

  • 《统计学习方法》的python代码实现(github标星7200+)

  • 精心整理和翻译的机器学习的相关数学资料

  • 首发:深度学习入门宝典-《python深度学习》原文代码中文注释版及电子书

  • 图解word2vec(原文翻译)

备注:加入本站微信群或者qq群,请回复“加群

加入知识星球(4100+用户,ID:92416895),请回复“知识星球

Python实现快速排序(非递归实现)相关推荐

  1. 排序下---(冒泡排序,快速排序,快速排序优化,快速排序非递归,归并排序,计数排序)

    排序上 排序上 交换类排序 基本思想:所谓交换,就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置,交换排序的特点是:将键值较大的记录向序列的尾部移动,键值较小的记录向序列的前部移动. ...

  2. python实现二叉树非递归前中后序遍历

    python实现二叉树非递归前中后层序遍历 二叉树是数据结构中重要的一部分,本文简单介绍用python实现二叉树的前中后序遍历,包括递归和非递归思路算法. # -*- 二叉树 begin -*- # ...

  3. python冒泡排序算法非递归_python 冒泡排序,递归

    今天LeetCode的时候暴力求解233 问题: 给定一个整数 n,计算所有小于等于 n 的非负数中数字1出现的个数. 例如: 给定 n = 13, 返回 6,因为数字1出现在下数中出现:1,10,1 ...

  4. 排序算法:快速排序算法实现及分析(递归形式和非递归形式)

    快速排序算法介绍 从名字上就可以看出快速排序算法很嚣张,直接以快速命名.确实快速排序 的确很快速,被列为20世纪十大算法之一.程序员难道不应该掌握么.快速排序(Quick Sort)的基本思想是:通过 ...

  5. 【排序】冒泡排序与快速排序(三个版本+非递归图示详解哦)

    全文目录 引言 冒泡排序 快速排序 思路 实现 Hoare版本 快排优化 挖坑法 前后指针法 快排非递归版本 思路 实现 总结 引言 在这篇文章中,将继续介绍排序算法:冒泡排序与快速排序: 它们都属于 ...

  6. python快速排序递归与非递归

    快速排序递归与非递归python 写在前面 快速排序的递归函数 快排的切分函数 快排的非递归函数 完整的源代码 写在前面 众所周知,快速排序相对于选择排序,插入排序,冒泡排序等初级排序有着天然的优势. ...

  7. c语言栈的实现以及操作_python模拟栈的操作实现非递归方式的快速排序算法

    本文首发地址: https://yishuihancheng.blog.csdn.net/article/details/76185032 欢迎关注我的博客[Together_CZ],我是沂水寒城! ...

  8. 判断某数组是不是二叉树的后序遍历序列 python递归与非递归解法

    python 递归 class Solution:def VerifySquenceOfBST(self, sequence):# write code hereif len(sequence) &l ...

  9. 后序遍历的非递归算法python_刷题系列 - Python用非递归实现二叉树后续遍历

    顺便把Python用非递归实现二叉树后续遍历也写了. 其实前序中序和后续都是针对父节点说的.比如下面这个最简单二叉树. 前序就是ABC,父节点A在前 中序就是BAC,父节点A在中间 后序就是BCA,父 ...

最新文章

  1. 如何更新Jenkins作业发布config.xml
  2. php实现第三方邮箱登录_PHP实现用户异地登录提醒功能的方法
  3. 磁卡门锁怎么配卡_样式多的铜工艺品怎么设计请查看_江西南昌皇巢|铜门||别墅铜门|...
  4. 蓝牙扫描过程解析_智慧定位系统之蓝牙网关在室内定位技术的原理浅析-新导智能...
  5. 【算法分析与设计】所有结点对的最短路径算法
  6. Spring中的Aop底层原理
  7. java之重定向与转发
  8. Oracle常用函数笔记
  9. java 10什么意思_详解:Java 10的10个新特性
  10. Python使用jieba库实现分词统计词频
  11. Tox —— 保证通话信息安全的即时聊天工具
  12. 融云即时通讯云助力多家直播平台构建社交升级
  13. java基于uni-app框架的民宿客房预订系统 小程序
  14. win10便签常驻桌面_有没有比较好用的电脑桌面待办事项软件?桌面便签可以了解一下...
  15. 【Python 3 的基础语法】
  16. MPB:中农冯固组-​利用13C-DNA-SIP法示踪根际和菌丝际活性解磷细菌
  17. LaTex中文编辑入门
  18. 奶爸日记7 - 新手第一次开车上路
  19. 高级性能测试系列《13.察看结果树中的显示顺序、 响应的提取--json提取器》
  20. 视频有黑边怎么办?如何裁剪视频画面的黑边?

热门文章

  1. windows自动修复失败,无法启动
  2. jquery插件之选项卡
  3. 查询反模式 - 隐式的列
  4. delphi webbrowser 经常用法演示样例
  5. 基于HBASE的并行计算架构之rowkey设计篇
  6. S3C2410中断系统
  7. poj 2528 Mayor's posters (线段树+离散化)
  8. 黑马程序员----银行业务调度系统面试题
  9. java 算法_JAVA经典算法40题
  10. activex for chrome扩展程序 下载”_提升前端开发效率:你应该知道的10个Chrome扩展程序...