当前位置: 首页 > news >正文

Python算法L2:排序算法(详细版)

目录

        • 前言
        • 1. 冒泡排序 (Bubble Sort)
        • 2. 选择排序 (Selection Sort)
        • 3. 插入排序 (Insertion Sort)
        • 4. 快速排序 (Quick Sort)
        • 5. 归并排序 (Merge Sort)
        • 6. 堆排序 (Heap Sort)
        • Python内置的`sorted()`函数
      • 总结

前言

排序算法是计算机科学中一个非常基本但又极为重要的主题。无论是数据分析、搜索算法,还是日常编程任务中,排序操作都频繁出现。Python 作为一个高级编程语言,内置了强大的排序功能,同时也允许开发者根据需求自定义排序算法。在这篇博客中,我们将介绍几种常见的排序算法,并展示如何在 Python 中实现它们。

1. 冒泡排序 (Bubble Sort)

冒泡排序是一种简单的交换排序算法。它的基本思想是反复比较相邻的元素,如果前一个元素大于后一个元素,就交换它们的位置,直到整个序列有序为止。

代码示例:

def bubble_sort(arr):n = len(arr)for i in range(n):for j in range(0, n-i-1):if arr[j] > arr[j+1]:arr[j], arr[j+1] = arr[j+1], arr[j]return arr

时间复杂度:

  • 最优时间复杂度:O(n) (当列表已经有序)
  • 平均时间复杂度:O(n²)
  • 最差时间复杂度:O(n²)

冒泡排序虽然简单,但效率较低,特别是对于大规模数据集。

2. 选择排序 (Selection Sort)

选择排序每次从未排序的部分选择最小的元素,将其放到已排序部分的末尾。它是一种不稳定的排序算法。

代码示例:

def selection_sort(arr):n = len(arr)for i in range(n):min_idx = ifor j in range(i+1, n):if arr[j] < arr[min_idx]:min_idx = jarr[i], arr[min_idx] = arr[min_idx], arr[i]return arr

时间复杂度:

  • 最优时间复杂度:O(n²)
  • 平均时间复杂度:O(n²)
  • 最差时间复杂度:O(n²)

选择排序通常比冒泡排序更高效,因其交换次数较少。

3. 插入排序 (Insertion Sort)

插入排序通过逐一将元素插入到有序部分来构建最终的排序列表。它的工作方式类似于扑克牌的排序过程,逐个将每张牌插入到正确的位置。

代码示例:

def insertion_sort(arr):for i in range(1, len(arr)):key = arr[i]j = i - 1while j >= 0 and key < arr[j]:arr[j + 1] = arr[j]j -= 1arr[j + 1] = keyreturn arr

时间复杂度:

  • 最优时间复杂度:O(n) (当列表已经有序)
  • 平均时间复杂度:O(n²)
  • 最差时间复杂度:O(n²)

插入排序对于小型数据集非常有效,并且在数据几乎有序的情况下表现优异。

4. 快速排序 (Quick Sort)

快速排序是一种基于分治法的高效排序算法。它通过选择一个基准点(pivot),将数组分为两部分,一部分比基准点小,另一部分比基准点大,然后递归地对这两部分进行排序。

代码示例:

def quick_sort(arr):if len(arr) <= 1:return arrpivot = arr[len(arr) // 2]left = [x for x in arr if x < pivot]middle = [x for x in arr if x == pivot]right = [x for x in arr if x > pivot]return quick_sort(left) + middle + quick_sort(right)

时间复杂度:

  • 最优时间复杂度:O(n log n)
  • 平均时间复杂度:O(n log n)
  • 最差时间复杂度:O(n²) (当选择的基准点不合适)

快速排序是平均情况下最快的排序算法之一,但需要谨慎选择基准点。

5. 归并排序 (Merge Sort)

归并排序也是一种分治法的排序算法。它将数组分成两部分,对每一部分进行排序,然后合并两个有序的部分,直到整个数组有序。

代码示例:

def merge_sort(arr):if len(arr) <= 1:return arrmid = len(arr) // 2left = merge_sort(arr[:mid])right = merge_sort(arr[mid:])return merge(left, right)def merge(left, right):result = []i = j = 0while i < len(left) and j < len(right):if left[i] < right[j]:result.append(left[i])i += 1else:result.append(right[j])j += 1result.extend(left[i:])result.extend(right[j:])return result

时间复杂度:

  • 最优时间复杂度:O(n log n)
  • 平均时间复杂度:O(n log n)
  • 最差时间复杂度:O(n log n)

归并排序的优势在于稳定且在大规模数据时效率较高,缺点是需要额外的内存空间。

6. 堆排序 (Heap Sort)

堆排序是一种基于堆数据结构的排序算法。堆是一种特殊的完全二叉树,堆排序的基本思想是将数组转化为一个大顶堆(最大堆),然后从堆顶取出最大元素,将其与堆的最后一个元素交换,并对剩下的部分进行堆调整。

代码示例:

def heapify(arr, n, i):largest = ileft = 2 * i + 1right = 2 * i + 2if left < n and arr[left] > arr[largest]:largest = leftif right < n and arr[right] > arr[largest]:largest = rightif largest != i:arr[i], arr[largest] = arr[largest], arr[i]heapify(arr, n, largest)def heap_sort(arr):n = len(arr)for i in range(n // 2 - 1, -1, -1):heapify(arr, n, i)for i in range(n - 1, 0, -1):arr[i], arr[0] = arr[0], arr[i]heapify(arr, i, 0)return arr

时间复杂度:

  • 最优时间复杂度:O(n log n)
  • 平均时间复杂度:O(n log n)
  • 最差时间复杂度:O(n log n)

堆排序的优点在于它的空间复杂度为 O(1),且具有不错的时间复杂度。

Python内置的sorted()函数

Python 提供了内置的 sorted() 函数和列表对象的 sort() 方法,都是基于 Timsort 实现的。Timsort 是一种混合排序算法,结合了归并排序和插入排序的优点,具有非常好的性能。

代码示例:

arr = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]
sorted_arr = sorted(arr)
arr.sort()

sorted() 函数返回一个新的已排序列表,而 sort() 方法则在原地对列表进行排序。

时间复杂度:

  • 最优时间复杂度:O(n)
  • 平均时间复杂度:O(n log n)
  • 最差时间复杂度:O(n log n)

总结

不同的排序算法在不同的场景下具有不同的优势。对于小型数据集,简单的冒泡排序、插入排序可能表现得足够好。而在大数据集下,快速排序、归并排序以及 Python 的 Timsort 通常更为合适。选择排序算法时,除了考虑时间复杂度,还应考虑算法的空间复杂度和稳定性。

通过理解和实现这些经典的排序算法,不仅能提升我们对算法的理解,还能帮助我们在实际开发中选择最合适的算法来提高程序性能。在下一课中,我们将继续深入学习Python的算法内容,进一步提升编程能力。关注我,更多精彩内容敬请期待《Python算法》系列博客的下一课–Python深度优先搜索!

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 从零到精通,一步步教你玩转在线思维导图,提升思维力
  • 秋招转型上岸大模型算法岗,咋做到的?
  • 使用[KafkaStreams流计算框架实时计算产生报警(升级报警)
  • AI基础 -- 练手之预测耗时方案
  • vllm 推理qwen gguf模型使用案例;openai接口调用、requests调用
  • ploarDNctf靶场[CRYPTO]你知道M型栅栏密码吗?、一闪一闪亮星星、interesting
  • JavaScript ES6+ 新特性
  • 《费曼学习法》
  • Android 12系统源码_输入系统(二)InputManagerService服务
  • Kubernetes存储Volume
  • 【STM32】时钟体系
  • 凌鸥学园电机控制学习盛宴,诚邀您的加入
  • 若依后端添加子模块swagger分区
  • MySQL中的事物详解
  • Electron程序逆向(asar归档解包)
  • 9月CHINA-PUB-OPENDAY技术沙龙——IPHONE
  • @jsonView过滤属性
  • 【知识碎片】第三方登录弹窗效果
  • CAP 一致性协议及应用解析
  • CentOS6 编译安装 redis-3.2.3
  • CoolViewPager:即刻刷新,自定义边缘效果颜色,双向自动循环,内置垂直切换效果,想要的都在这里...
  • iBatis和MyBatis在使用ResultMap对应关系时的区别
  • IE报vuex requires a Promise polyfill in this browser问题解决
  • iOS仿今日头条、壁纸应用、筛选分类、三方微博、颜色填充等源码
  • swift基础之_对象 实例方法 对象方法。
  • Terraform入门 - 1. 安装Terraform
  • ubuntu 下nginx安装 并支持https协议
  • 阿里云应用高可用服务公测发布
  • 前端之React实战:创建跨平台的项目架构
  • 浅谈web中前端模板引擎的使用
  • 山寨一个 Promise
  • 继 XDL 之后,阿里妈妈开源大规模分布式图表征学习框架 Euler ...
  • ​​快速排序(四)——挖坑法,前后指针法与非递归
  • ​低代码平台的核心价值与优势
  • ​学习笔记——动态路由——IS-IS中间系统到中间系统(报文/TLV)​
  • !!Dom4j 学习笔记
  • #pragma pack(1)
  • (八)光盘的挂载与解挂、挂载CentOS镜像、rpm安装软件详细学习笔记
  • (二)学习JVM —— 垃圾回收机制
  • (附表设计)不是我吹!超级全面的权限系统设计方案面世了
  • (附源码)php投票系统 毕业设计 121500
  • (附源码)springboot车辆管理系统 毕业设计 031034
  • (接上一篇)前端弄一个变量实现点击次数在前端页面实时更新
  • (切换多语言)vantUI+vue-i18n进行国际化配置及新增没有的语言包
  • (使用vite搭建vue3项目(vite + vue3 + vue router + pinia + element plus))
  • (四)【Jmeter】 JMeter的界面布局与组件概述
  • (完整代码)R语言中利用SVM-RFE机器学习算法筛选关键因子
  • (转)重识new
  • (自用)learnOpenGL学习总结-高级OpenGL-抗锯齿
  • (总结)Linux下的暴力密码在线破解工具Hydra详解
  • .halo勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .L0CK3D来袭:如何保护您的数据免受致命攻击
  • .NET Conf 2023 回顾 – 庆祝社区、创新和 .NET 8 的发布
  • .Net Core 微服务之Consul(二)-集群搭建
  • .NET学习教程二——.net基础定义+VS常用设置