python实现常见排序算法

python实现常见排序算法

快速排序

思想:取出第一个元素把它放到序列的中间某一个正确位置,以它进行分割成左边和右边,再分别对左边和右边进行取元素分割(递归)

递归实现

def quicksort(array):if len(array) < 2: # 递归终止条件:数组少于2则是一个元素或空元素无需排序return arrayelse:mid = array[0]  # 先确定一个中间点less = [i for i in array[1:] if i <= mid] # 生成一个列表的元素全部小于等于中间基准点more = [i for i in array[1:] if i > mid] # 生成一个列表的元素全部大于中间基准点return quicksort(less) + [mid] + quicksort(more) # 列表拼接,左边继续调用自身排序,右边同理#验证结果
print(quicksort([1, 4, 2, 6, 4, 5, 8, 3]))
#===>[1, 2, 3, 4, 4, 5, 6, 8]  

时间复杂度

  • 最优时间复杂度:O(nlogn)
  • 最坏时间复杂度:O(n*n) ==>深度最坏的n,单层是n,所以n*n
  • 稳定性:不稳定

对O(nlogn)的类比通俗理解:
递归调用函数可以理解为二叉树,调用树的深度是O(log n),也就是要切分logn次,而调用的每一层次结构总共全部仅需要O(n)的时间,所以二者相乘得O(nlogn),我这里说的调用树其实是调用栈后面也会详细说道快速排序的时间复杂度。
在最好的情况,每次我们运行一次分区,我们会把一个数列分为两个几近相等的片段。这个意思就是每次递归调用处理一半大小的数列。

选择排序

思想: 假设最后一个元素是最大值,现在要从左到右(除了最后一个)依次与最大值进行比较,如果大于最大值就将两个位置进行交换。
代码实现

def selection_sort(array):for i in range(len(array)-1,0,-1): #产生[n-1,n-2,...2,1]for j in range(i):if array[j] > array[i]:array[j], array[i] = array[i], array[j]return array

时间复杂度

  • 最优时间复杂度:O(n*n)
  • 最坏时间复杂度:O(n*n) ==>深度最坏的n,单层是n,所以n*n
  • 稳定性:不稳定

冒泡排序

思想:所谓冒泡,就是将元素两两之间进行比较,谁大就往后移动,直到将最大的元素排到最后面,接着再循环一趟,从头开始进行两两比较,而上一趟已经排好的那个元素就不用进行比较了。
一级优化实现
考虑整数数组就是有序的特殊情况,设定一个变量为False,如果元素之间交换了位置,将变量重新赋值为True,最后再判断,在一次循环结束后,变量如果还是为False,则break退出循环,结束排序。

def bubble_sort(array):for i in range(len(array) - 1): # 外层循环n次保证所有数都在正确的位置上flag = False  # 标识for j in range(len(array) - 1 - i): #内层循环一次代表最后一个数就是最大的if array[j] > array[j + 1]:array[j], array[j + 1] = array[j + 1], array[j]flag = True # 只要需要进行交换,则进入循环改为Trueif not flag: #如果没进入循环体说明原来的数据是有序的break # 直接跳出循环return array

二级优化实现
上面这种写法还有一个问题,就是每次都是从左边到右边进行比较,这样效率不高,你要考虑当最大值和最小值分别在两端的情况。写成双向排序提高效率,即当一次从左向右的排序比较结束后,立马从右向左来一次排序比较。

def bubble_sort(array):for i in range(len(array) - 1):flag = Falsefor j in range(len(array) - 1 - i):if array[j] > array[j + 1]:array[j], array[j + 1] = array[j + 1], array[j]flag = Trueif flag: # 上个循环体循环一次保证最后一个数是最大的flag = False for j in range(len(array) - 2 - i, 0, -1): # 从倒数第二个数开始,从后往前再浮动比较一下if array[j - 1] > array[j]:array[j], array[j - 1] = array[j - 1], array[j]flag = Trueif not flag:breakreturn array

时间复杂度

  • 最优时间复杂度:O(n) ==> 已经是有序的了
  • 最坏时间复杂度:O(n*n)
  • 稳定性:稳定==>每次判断如果相等,那就不交换,位置不变

插入排序

思想:认定第一个元素是有序,取出第二个元素进行判断插入到左边的正确位置上,这是一个内循环,外循环遍历不包括第一个元素的下标进行重复操作。

def insert_sort(array):for i in range(1, len(array)): j = i # 从第二个元素开始while j > 0 :if array[j-1] > array[j]:array[j-1], array[j] = array[j], array[j-1]j -= 1else: # 如果操作就是有序序列,每次都执行else退出循环体,提升效率break

时间复杂度

  • 最优时间复杂度:O(n)
  • 最坏时间复杂度:O(n*n)
  • 稳定性:稳定==> 如果数值相等,在代码中对=不进行处理,所以也不交换位置保证原来的位置顺序

归并排序:

思路:将数组拆分成一个一个的小数组,然后进行临近合并,合并的时候进行判断排序
递归实现

def merge(left, right):"""合并排序"""L, R = 0, 0slist =  []while L < len(left) and R < len(right):if left[L] <= right[R]:slist.append(left[L])L += 1else:slist.append(right[R])R += 1# 循环体结束,对称的数据都比较完了,可能出现不对称的话,将剩余数据追加到slist中slist += left[L:]slist += right[R:]return slist
def merge_sort(arr):if len(arr) < 2:return arr# 开始递归拆分数组mid = len(arr) // 2left_list = merge_sort(arr[:mid])right_list = merge_sort(arr[mid:])# 开始合并return merge(left_list,right_list)

时间复杂度

  • 最优时间复杂度:O(nlogn)
  • 最坏时间复杂度:O(nlogn)
  • 稳定性:稳定

排序算法时空复杂度总结

排序算法总结
这里只说一下快速排序和归并排序
快速排序我们递归调用栈的思想来理解,结合我后一篇文章学习递归来理解。

最好的情况, 快速排序的每次选的中间值mid都是真正的中间值,调用栈的高度(函数调用层数)就为O(logn),而每层需要时间为O(n),因此整个算法需要的时间为O(n) * O(log n) = O(n log n)。这就是最佳情况。

最糟糕情况,O(n)层,因此该算法的运行时间为O(n) * O(n) = O(n2)

最佳情况也是平均情况。 只要你每次都随机地选择一个数组元素作为基准值,快速排序的平均运行时间就将为O(n log n)。快速排序是最快的排序算法之一,也是D&C(分而治之)典范。

这里需要记住的是,快速排序一般情况下是比归并排序的速度要快

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/500114.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CoreAnimation编程指南(二)渲染架构

1.虽然核心动画的图层和Cocoa的视图在很大程度上没有一定的相似性&#xff0c;但是他们两者最大的区别是&#xff0c;图层不会直接渲染到屏幕上。2.在模型-视图-控制器&#xff08;model-view-controller&#xff09;概念里面NSView和UIView是典型的视图部分&#xff0c;但是在…

学习递归

算法之递归 递归思想 递归就是函数自己调用自己&#xff0c;会使代码逻辑很清晰&#xff0c;但是Stack Overflow上有说的一句话&#xff1a;“如果使用循环&#xff0c;程序的性能可能更高&#xff1b;如果使用递归&#xff0c;程序可能更容易理解。如何选择要看什么对你来说…

CoreAnimation编程指南(三)几何变换

本章介绍图层的几何组成部分&#xff0c;及他们之间的相互关&#xff0c;同时介绍如何变换矩阵可以产生复杂的视觉效果。一、图层的坐标系1.图层的坐标系在不同平台上面具有差异性。在iOS系统中&#xff0c;默认的坐标系统原点在图层的中心左上角地方&#xff0c;原点向右和向下…

队列和栈

栈 一张图可以简单的说明 为了达到时间复杂度最低&#xff1a;选择的是python列表实现栈&#xff0c;而列表是顺序表 入栈push的时候选择在列表的尾部进行添加元素&#xff0c;出栈在列表尾部弹出 class Stack(object):"""栈"""def __init__(…

CoreAnimation编程指南(四)图层树结构

图层不但给自己提供可视化的内容和管理动画&#xff0c;而且充当了其他图层的容器类&#xff0c;构建图层层次结构。 本章介绍了图层层次结构&#xff0c;以及如何操纵该图层层次结构。一、什么是图层树的层次结构1.图层树是核心动画里面类似Cocoa视图的层次结构。比如一个NSVi…

学习散列表

回顾一下简单查找和二分查找 杂货店商品对应的价格举例&#xff1a; 简单查找就是拿出商品价目本&#xff0c;这个价目本并不是有序的&#xff0c;顾客问苹果多少钱&#xff0c;需要一个一个去查找某一个商品的价格&#xff0c;需要O(n)时间。 同样是一个价目本&#xff0c;但…

CoreAnimation编程指南(五)图层内容

当我们使用Cocoa的视图的时候&#xff0c;我们必须继承NSView或者UIView并且重载函数drawRect:来显示任何内容。但是CALayer实例可以直接使用&#xff0c;而无需继承子类。因为CALayer是一个键-值编码兼容的容器类&#xff0c;你可以在实例里面存储任意值&#xff0c;所以子类实…

SHA算法

回顾散列算法 我的上篇文章&#xff1a;学习散列表 在上篇文章杂货铺的示例中&#xff0c;我们希望散列函数的结果是均匀分布的。散列函数接受一个字符串&#xff0c;并返回一 个索引号。 安全散列算法&#xff08;secure hash algorithm&#xff0c; SHA&#xff09;函数 给…

python实现搜索之二分查找

搜索 搜索是在一个项目集合中找到一个特定项目的算法过程。搜索通常的答案是真的或假的&#xff0c;因为该项目是否存在。 搜索的几种常见方法&#xff1a;顺序查找、二分法查找、二叉树查找、哈希查找 二分法查找 二分查找又称折半查找&#xff0c;优点是比较次数少&#x…

CoreAnimation编程指南(九)图层布局

NSView提供了经典的“stuts and springs”模式&#xff0c;用于视图调整大小的时候把关联到它父图层的视图重新调整位置。图层支持该模式&#xff0c;而且Mac OS X上面的核心动画提供了一个更通用的布局管理器机制&#xff0c;允许开发者自己写他们自己的布局管理器。可以为图层…

数据库优化、数据库基础等常用知识点总结

建表优化 1&#xff09;数据库范式 第一范式&#xff08;1NF&#xff09;&#xff1a;强调的是列的原子性&#xff0c;即列不能够再分成其他几列。 如电话列可进行拆分—家庭电话、公司电话第二范式&#xff08;2NF&#xff09;&#xff1a;首先是 1NF&#xff0c;另外包含两…

一片文章概括大部分python面试基础常考题(部分有详解)

本片文章部分参考地址&#xff1a;https://segmentfault.com/a/1190000018737045 python是动态解释性的强类型定义语言 强类型&#xff1a;不允许不同类型相加。例如&#xff1a;整形字符串会报类型错误。 动态&#xff1a;不使用显示数据类型声明&#xff0c;且确定一个变量…

经典逻辑编程题(本文用python实现)

在一个二维数组中&#xff08;每个一维数组的长度相同&#xff09;&#xff0c;每一行都按照从左到右递增的顺序排序&#xff0c;每一列都按照从上到下递增的顺序排序。请完成一个函数&#xff0c;输入这样的一个二维数组和一个整数&#xff0c;判断数组中是否含有该整数。 思…

CoreData简介

一、概念 1.Core Data 是数据持久化存储的最佳方式 2.数据最终的存储类型可以是&#xff1a;SQLite数据库&#xff0c;XML&#xff0c;二进制&#xff0c;内存里&#xff0c;或自定义数据类型 3.好处&#xff1a;能够合理管理内存&#xff0c;避免使用sql的麻烦&#xff0c;高效…

NSZombieEnabled使用

我们做iOS 程序开发时经常用遇到 EXC_BAD_ACCESS 错误导致 Crash&#xff0c;出现这种错误时一般 Xcode 不会给我们太多的信息来定位错误来源&#xff0c;只是在应用 Delegate 上留下像Thread 1: Program received signal:"EXC_BAD_ACCESS"&#xff0c;让问题无从找起…

通过终端,查看sqlite3的存储文件

在调试应用的时候&#xff0c;可以查看数据库里的数据。 1、定位到模拟器的目录 cd ~/Library/Application\ Support/iPhone\ Simulator 2、查找文件名包含 OrgChart.sqlite的文件&#xff0c;并打印路径 find . -name "OrgChart.sqlite" –print 输出&#xff1a; .…

iOS的事件分发

移动平台上的开发主要关注数据以及数据的处理&#xff0c;事件的处理以及UI。所以事件的分发处理是很重要的一个环节&#xff0c;对于一个平台的优劣来说也是一项重要的参数。如果事件的分发设计的不好&#xff0c;一些复杂的UI场景就会变得很难写甚至没法写。从小屏没有触摸的…

iOS开发ARC入门和使用

本文部分实例取自iOS 5 Toturail一书中关于ARC的教程和公开内容&#xff0c;仅用于技术交流和讨论。请不要将本文的部分或全部内容用于商用&#xff0c;谢谢合作。 欢迎转载本文&#xff0c;但是转载请注明本文出处&#xff1a;http://www.onevcat.com/2012/06/arc-hand-by-han…

UIBezierPath 的使用介绍

使用UIBezierPath类可以创建基于矢量的路径。此类是Core Graphics框架关于path的一个封装。使用此类可以定义简单的形状&#xff0c;如椭圆或者矩形&#xff0c;或者有多个直线和曲线段组成的形状。1.Bezier Path 基础UIBezierPath对象是CGPathRef数据类型的封装。path如果是基…

iOS中的XML解析

解析方式分类: 解析 XML 通常有两种方式&#xff0c;DOM 和 SAX&#xff1a;DOM解析XML时&#xff0c;读入整个XML文档并构建一个驻留内存的树结构&#xff08;节点树&#xff09;&#xff0c;通过遍历树结构可以检索任意XML节点&#xff0c;读取它的属性和值。 iOS中XML解析是…