Python - 排序( 插入, 冒泡, 快速, 二分 )
插入排序
算法分析
两次循环, 大循环对队列中的每一个元素拿出来作为小循环的裁定对象
小循环对堆当前循环对象在有序队列中寻找插入的位置
性能参数
空间复杂度 O(1)
时间复杂度 O(n^2)
详细代码解读
import random def func(l):
# 外层循环: 对应遍历所有的无序数据
for i in range(1, len(l)):
# 备份 取出数据
temp = l[i]
# 记录取出来的下标值
pos = i
# 内层循环: 对应从后往前扫描所有有序数据
"""
i - 1 > 从最后一个有序数据开始, 即无序数据前一位
-1 > 扫描到下标 0 为止, 要包括第一个, 因此设置 -1 往后推一位
-1 > 从后往前扫描
"""
for j in range(i - 1, -1, -1):
# 若有序数据 大于 取出数据
if l[j] > temp:
# 有序数据后移
l[j + 1] = l[j]
# 更新数据的插入位置
pos = j # 对应所有有序数据比取出数据大的情况
# 若有序数据 小于/等于 取出数据
else:
pos = j + 1
break
# 在指定位置插入数据
l[pos] = temp if __name__ == '__main__':
l = list(range(1, 13))
random.shuffle(l)
func(l)
print(l)
简单实例
import random def foo(l):
for i in range(1, len(l)):
temp = l[i]
pos = i
for j in range(i - 1, -1, -1):
if temp < l[j]:
l[j + 1] = l[j]
pos = j
else:
pos = j + 1
break l[pos] = temp
return l if __name__ == '__main__':
l = list(range(13))
random.shuffle(l)
print(l) # [12, 0, 4, 5, 6, 2, 11, 10, 8, 7, 3, 1, 9]
print(foo(l)) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
冒泡排序
算法分析
两两比较, 每次比较出一个未排序队列的最大值,让只在队列右侧排列
两次循环, 大循环每次输出一个当前最大值.
小循环进行具体的数值比对
性能参数
空间复杂度 O(1)
时间复杂度 O(n^2)
详细代码
"""
入学后, 第一次上体育课, 体育老师要求大家排队, 按照身高从低到高排队
获取全班 10 名同学的身高
""" """
外层循环
大循环控制总循环次数
内层循环
小循环控制如歌得出这个最大值
计算大小, 然后彼此交换
""" import random """
基础版
""" def func(l):
# 外层循环: 走访数据的次数
for i in range(len(l) - 1):
# 内层循环: 每次走访数据时, 相邻对比次数
for j in range(len(l) - i - 1):
# 要求从低到高
# 如次序有误就交换
if l[j] > l[j + 1]:
l[j], l[j + 1] = l[j + 1], l[j] # 遍历次数
print("走访次数:", i + 1) """
升级版
""" def foo(l):
# 外层循环: 走访数据的次数
for i in range(len(l) - 1):
# 设置是否交换标志位
flag = False
# 内层循环: 每次走访数据时, 相邻对比次数
for j in range(len(l) - i - 1):
# 要求从低到高
# 如次序有误就交换
if l[j] > l[j + 1]:
l[j], l[j + 1] = l[j + 1], l[j]
# 发生了数据交换
flag = True
# 如果未发生交换数据, 则说明后续数据均有序
if flag == False:
break # 跳出数据走访
# 遍历次数
print("走访次数:", i + 1) if __name__ == '__main__':
l = list(range(1, 11))
random.shuffle(l)
print("排序前:", l)
# func(l)
foo(l)
print("排序后:", l)
简单代码
import random def foo(l):
for i in range(len(l) - 1):
for j in range(len(l) - i - 1):
if l[j] > l[j + 1] and j != len(l):
l[j], l[j + 1] = l[j + 1], l[j] return l if __name__ == '__main__':
l = list(range(13))
random.shuffle(l)
print(l) # [2, 3, 0, 7, 8, 11, 10, 6, 4, 5, 12, 1, 9]
print(foo(l)) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
升级版代码
import random def foo(l):
for i in range(len(l) - 1):
flag = 1
for j in range(len(l) - i - 1):
if l[j] > l[j + 1] and j != len(l):
l[j], l[j + 1] = l[j + 1], l[j]
flag = 0
if flag:
break
return l if __name__ == '__main__':
l = list(range(13))
random.shuffle(l)
print(l) # [0, 9, 1, 3, 8, 12, 6, 5, 2, 7, 10, 11, 4]
print(foo(l)) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
快速排序
算法分析
首先任意取一个元素作为关键数据 ( 通常取首元素
然后将所有比他小的数据源放在其前面, 所有比它大的放在他后面
通过一次排序将要排序的数据分为独立的两部分
然后按照该方法再递归对两部分数据进行快速排序
性能参数
时间复杂度 O(nlogn)
空间复杂度 O(logn)
稳定性 不稳定
详细代码
# 快速排序
import random def quick(l):
# 递归退出条件
# 仅剩一个元素无需继续分组
if len(l) < 2:
return l
# 设置关键数据
a = l[0]
# 找出所有比 a 大的数据
big = [x for x in l if x > a]
# 找出所有比 a 小的数据
small = [x for x in l if x < a]
# 找出所有与 a 相等的数据
same = [x for x in l if x == a]
# 拼接数据排序的结果
return quick(small) + same + quick(big) if __name__ == '__main__':
l = list(range(1, 25))
random.shuffle(l)
l = quick(l)
print(l)
二分查找
算法分析
只能对有序队列进行查找, 利用和中间值进行对比, 然后基于判断将队列丢弃一半的方式
性能参数
时间复杂度 O(log2 n)
空间复杂度 O(1)
详细代码
"""
1. 切分成两部分,取中间值来判断
2. 如何定义下一次的范围:
大于中间值, 在左侧找
小于中间值, 在右侧找
3. 查找失败情况: 中间值 小于左端 或者 中间值 大于 右端
""" """
扑克牌 只取 黑桃 13 张, 用 1-13 表示, 将牌从小到大排序, 反面向上排成一排, 找到黑桃 6 的位置
""" """
l 原始数据
k 待查找数据
left 首元素下标值
right 尾元素下标值
""" """
递归方式实现
""" def func(l, k, left, right):
# 递归退出条件
if left > right:
# 查找结束
return -1
# 获取中间元素对应下标值
middle = (left + right) // 2
# 对比中间元素 和 查找元素
if l[middle] == k:
return middle
elif l[middle] > k:
# 中间值 大于 查找值
# 查找范围是 中分后的 左边部分
# 左侧下标值不变, 右侧下标值变为 middle 前一位
right = middle - 1
return func(l, k, left, right)
else:
# 中间值 小于 查找值
# 查找范围是 中分后的 右边部分
# 左侧下标值变为 middle 后一位, 右侧下标值不变
left = middle + 1
return func(l, k, left, right) """
循环方式实现
""" def foo(l, k):
left = 0
right = len(l) - 1
while left <= right:
mid = (left + right) // 2
if l[mid] > k:
right = mid - 1
elif l[mid] < k:
left = mid + 1
elif l[mid] == k:
return midreturn -1 if __name__ == '__main__':
# l = list(range(1, 14))
# k = 8
# right = len(l) - 1
# res = func(l, k, 0, right) l = list(range(1, 14))
k = 10
right = len(l) - 1
res = foo(l, k)
if res == -1:
print("查找失败")
else:
print("查找成功, 第 %d 张拿到" % res)
简单代码
def foo(l, k):
left = 0
right = len(l) - 1
while left <= right:
mid = (left + right) // 2
if l[mid] > k:
right = mid - 1
elif l[mid] < k:
left = mid + 1
elif l[mid] == k:
return mid
return -1 if __name__ == '__main__':
l = list(range(13))
print(l) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
print(foo(l, 8)) #
总结
冒泡排序
重复走访所有要排序的数据,
依次比较每两个相邻的元素,
如果两者次序错误就交换
重复上面过程 直到没有需要被调换的内容为止
插入排序
将数据插入到已经有序的数据中, 从而得到一个新的有序数据
默认首元素自然有序, 取出下一个元素, 对已经有序的数据从后向前扫描
若扫描的有序数据大于取出数据, 则该有序数据后移
若扫描的有序数据小于取出数据, 则在该有序数据后插入取出数据
若扫描的所有的有序数据大于取出数据, 则在有序数据的首位插入取出数据
特点
数据只移动不交换, 优于冒泡
快速排序
首先任意取一个元素作为关键数据 ( 通常取首元素 )
然后将所有比他小的数据源放在其前面
(从小到大)所有比它大的放在他后面
通过一次排序将要排序的数据分为独立的两部分
然后按照该方法再递归对两部分数据进行快速排序
特点
每次若能均匀分组则排序速度最快, 但是不稳定
Python - 排序( 插入, 冒泡, 快速, 二分 )的更多相关文章
- python排序算法-冒泡和快速排序,解答阿里面试题
''常见的排序算法\ 插入排序/希尔排序/直接排序/堆排序 冒泡排序/快速排序/归序排序/基数排序 给定一个列表,将这个列表进行排序,要求:> 时间复杂度要小于O(n^2) 复杂度:1.时间复杂 ...
- Java四种排序:冒泡,选择,插入,二分(折半插入)
四种排序:冒泡,选择,插入,二分(折半插入) public class Test{ // public static void main(String[] args) { // Test t=new ...
- python排序算法实现(冒泡、选择、插入)
python排序算法实现(冒泡.选择.插入) python 从小到大排序 1.冒泡排序: O(n2) s=[3,4,2,5,1,9] #count = 0 for i in range(len(s)) ...
- java 基础排序(冒泡、插入、选择、快速)算法回顾
java 基础排序(冒泡.插入.选择.快速)算法回顾 冒泡排序 private static void bubbleSort(int[] array) { int temp; for (int i = ...
- 左神算法第一节课:复杂度、排序(冒泡、选择、插入、归并)、小和问题和逆序对问题、对数器和递归(Master公式)
第一节课 复杂度 排序(冒泡.选择.插入.归并) 小和问题和逆序对问题 对数器 递归 1. 复杂度 认识时间复杂度常数时间的操作:一个操作如果和数据量没有关系,每次都是固定时间内完成的操作,叫做常数 ...
- 44.python排序算法(冒泡+选择)
一,冒泡排序: 是一种简单的排序算法.它重复地遍历要排序的数列,一次比较两个,如果他们的排序错误就把他们交换过来. 冒泡排序是稳定的(所谓稳定性就是两个相同的元素不会交换位置) 冒泡排序算法的运作如下 ...
- 用 Python 排序数据的多种方法
用 Python 排序数据的多种方法 目录 [Python HOWTOs系列]排序 Python 列表有内置就地排序的方法 list.sort(),此外还有一个内置的 sorted() 函数将一个可迭 ...
- Python+Bottle+Sina SAE快速构建网站
Bottle是新生一代Python框架的代表,利用Bottle构建网站将十分简单. Sina SAE是国内较出名的云平台之一,十分适用于个人网站的开发或创业公司网站开发. 下面将介绍如果通过Pytho ...
- Python学习之---冒泡,选择,插入排序
Python学习之---冒泡,选择,插入排序 最近学习了python基础,写一下3大排序练练手: 1 ''' 2 Created on 2013-8-23 3 4 @author: codegeek ...
随机推荐
- 二十,基于K8S集群的PaaS简介
目录 一.概述 二.生产环境部署k8s,接下来我们描述一下在真正生产环境中我们部署k8s应该部署成什么样子 一.概述 1.通过以往的学习应该可以了解到k8s 和以往提到的devops概念更容易落地了. ...
- troubshooting-sqoop 导出 TiDB表数据报com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
2019-11-22 17:15:27,705 FATAL [IPC Server handler 13 on 44844] org.apache.hadoop.mapred.TaskAttemptL ...
- jenkins 配置主从机制(master-slaver)
1. 中文:系统管理——节点管理——新建节点(左上侧) 英文:Manage Jenkins——Manage Node——新建节点(左上侧) 2. 中文配图 英文配图: 3. 远程工作目录 以mac为例 ...
- TCP协议之网络延时
影响TCP 网络时延的因素硬件速度网络和服务器的负载请求和响应报文的尺寸客户端和服务器之间的距离TCP 协议的技术复杂性TCP协议产生的时延TCP 连接建立握手:TCP 慢启动拥塞控制:数据聚集的 N ...
- 使用Xcode Instruments定位APP稳定性问题
Xcode Instruments提供了各种各样的工具用来定位APP的各种稳定性问题.这里简单总结几个问题: 1. 内存泄漏 Xcode->Open Developer Tools->In ...
- IIS配置web.config 将带www域名转为不带www域名
在configuration节点中添加 <configuration> <system.webServer> <rewrite> <rules> < ...
- vuex直接修改state 与 用commit提交mutation来修改state的差异
一. 使用vuex修改state时,有两种方式: 1)可以直接使用 this.$store.state.变量 = xxx; 2)this.$store.dispatch(actionType, pa ...
- Kummer定理
简单学习了一下\(Kummer\)定理,参考了几篇不错的资料,放下链接 1.Legendre公式和Kummer定理 2.Kummer定理-超级Lucas定理-数论-组合数学-学习笔记 3.百度百科 证 ...
- UVALive 6858——分类讨论&&水题
题目 链接 题意:对于一个$n \times m$的矩阵的最外一圈,问是否能用$k \times 1$的方块填满 分析 考虑左右两边的情况,分类讨论,切记考虑所有可能的情形. #include< ...
- [React] Reduce Code Redundancy with Custom React Hooks
In this lesson, we'll cover how to create a custom React hook for managing the state of any input. T ...