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;函数 给…

CoreAnimation编程指南(六)动画

动画是当今用户界面的关键因素。当使用核心动画的时候&#xff0c;动画是自动完成的。没有动画的循环和计数器。你的应用程序不负负责重绘&#xff0c;也不负责跟踪动画的当前状态。动画在独立线程里面自动执行&#xff0c;没有和你的应用程序交互。本章提供了对动画类的概览&a…

CoreAnimation编程指南(七)图层Action

图层的行为在以下情况发生的时候被触发&#xff1a;从图层树里面插入或者删除一个图层&#xff0c;图层的属性值被修改了&#xff0c;或者程序显式要求。通常情况下&#xff0c;行为触发器是动画显示的结果所在。1.1 行为对象的角色一个行为对象是一个通过CAAction协议响应行为…

python实现搜索之二分查找

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

CoreAnimation编程指南(八)事务

图层的每个改变都是事务的一部分。CATransaction是核心动画类&#xff0c;它负责成批的把多个图层树的修改作为一个原子更新到渲染树。本章介绍了核心动画支持的两种事务。隐式事务和显式事务。1.1 隐式事务当图层树被没有获得事务的线程修改的时候将会自动创建隐式事务&#x…

写SQL语句需要注意的点

先回忆一下DDL和DML 创建表DDL create table t_xx(id int auto_increment primary key, name char(10),...) create table t_student( id int auto_increment primary key , name char(10), 外键id int, foreign key(外键id) references 外表t_class(外表id字段名) );插入数…

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

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

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

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

CoreAnimation编程指南(十)KVC

CAAnimation和CALayer类扩展了NSKeyValueCoding协议&#xff0c;给键添加默认值&#xff0c;扩展了封装协议&#xff0c;支持CGPoint、CGRect、CGSize和CATransform3D关键路径。1.1 键-值编码兼容的容器类CALayer和CAAnimation都是键-值编码兼容的容器类&#xff0c;允许你修改…

CoreImage使用介绍

一、概述CoreImage.framework从iOS5开始启用&#xff0c;它使我们很容易就能处理图片的各种效果&#xff0c;色彩&#xff0c;曝光&#xff0c;饱和度&#xff0c;变形等等。不仅功能强大&#xff0c;而且可以直接使用GPU&#xff0c;效率很高&#xff0c;甚至可以实时的对视频…

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

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

AssetsLibrary使用介绍

一、概述AssetsLibrary框架&#xff1a;从iOS4.0开始提供&#xff0c;可以通过它获取设备里的图片和视频等资料&#xff0c;以API的方式提供&#xff0c;而且界面式的&#xff0c;比UIImagePickerViewController灵活很多。既可以读又可以写。二、读取资料库中的全部资料1.大概步…

Objective-C成员变量声明方式探究

一、interface和 property 方式声明变量的区别1.你可以单独在interface中定义变量&#xff0c;而不用property定义&#xff1b;也可以只用property去定义&#xff0c;而不在interface中定义&#xff0c;当然用了property去定义&#xff0c;一般要在.m文件中用synthsize去合成相…