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

常见算法实现系列01 - 排序算法

常见排序算法python实现

1. 前言

​ 在刷leetcode题目的时候,发现秋招也会出现一些常见排序算法实现的问题,因此这里进行统一实现,方便后期复习。

​ 实现语言:Python。

目录

文章目录

    • 常见排序算法python实现
      • 1. 前言
      • 2. 冒泡排序
        • 2.1 原理
        • 2.2 实现
      • 3. 选择排序
        • 3.1 原理
        • 3.2 实现
      • 4. 插入排序
        • 4.1 原理
        • 4.2 实现
      • 5. 快速排序
        • 5.1 原理
        • 5.2 实现
      • 6. 归并排序
        • 6.1 原理
        • 6.2 实现
      • 7. 堆排序
        • 7.1 原理
        • 7.2 实现
      • 8. 总结

2. 冒泡排序

2.1 原理

​ 冒泡排序是一种简单直观的排序算法,它重复地遍历要排序的列表,比较相邻的元素,如果它们的顺序错误就交换它们。

​ 比如:

原本:5 4 6 1 3 2,从小到大排列
迭代第一次:
(1) 4 5 6 1 3 2,判断依据:4<5,换位置
(2) 4 5 6 1 3 2,判断依据:5<6,不换位置
(3) 4 5 1 6 3 2,判断依据:1<6,换位置
(4) 4 5 1 3 6 2,判断依据:3<6,换位置
(5) 4 5 1 3 2 6,判断依据:2<6,换位置
这就是第一次,然后继续迭代即可
  • 时间复杂度:O(n²),因为是双重循环
  • 空间复杂度:O(1),因为没有创建新的遍历,利用的原数组修改
2.2 实现

​ 通过上面的算法,发现是一个双重循环,第一重循环就是从开头到末尾,第二重循环就是从开头到后面已经排序后的前一个,然后再执行循环过程中,判断两者元素大小,是否需要交换位置即可,很简单:

从小到大排序

# 冒泡排序:从小到大
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# 尝试
arr = [64, 34, 25, 12, 22, 11, 90]
print(bubble_sort(arr))
# 输出:[11, 12, 22, 25, 34, 64, 90]

从大到小排序

​ 注意的区别就是判断大小,与上面的唯一区别就是:

if arr[j] > arr[j+1]:
## 变为
if arr[j] < arr[j+1]:

3. 选择排序

3.1 原理

​ 每次从未排序部分选择最小(或最大)元素放到已排序部分的末尾。

  • 时间复杂度:O(n²)
  • 空间复杂度:O(1)
3.2 实现

​ 首先,第一重循环肯定是从头到尾(索引为i),第二重循环就是从i+1到末尾,然后更新其中的最大或者最小值,然后移动即可。

​ 实现:

# 选择排序
def selection_sort(arr):n = len(arr)# 第一重循环for i in range(n):mn = i # or mx = i# 第二重循环for j in range(i+1,n):# 如果遇到更小的,就更新if arr[j] < arr[mn]: # or arr[j] > arr[mx]mn = j# 此时,找到了最小的,更新位置arr[i],arr[mn] = arr[mn],arr[i]return arr# 尝试
arr = [64, 34, 25, 12, 22, 11, 90]
print(selection_sort(arr))
# 输出
[11, 12, 22, 25, 34, 64, 90]

4. 插入排序

4.1 原理

​ 将数组分为"已排序"和"未排序"两部分,每次从未排序部分取出一个元素,插入到已排序部分的正确位置,直到所有元素都排序完成。

​ 它的工作方式类似于我们整理扑克牌:每次拿起一张牌,插入到手中已排序牌组的正确位置。

  • 时间复杂度:O(n²)
  • 空间复杂度:O(1)
4.2 实现

​ 分析一下这个算法。

​ 首先,肯定是双重循环,第一重循环仍然是从头到尾遍历(索引为i),第二重循环,需要不停遍历,找到当前元素i在已经排序的列表中的正确位置,这个肯定通过一个while循环实现即可。

# 插入排序
def insertion_sort(arr):# 第一重遍历n = len(arr)for i in range(1,n):# 当前要插入的元素key = arr[i]# 第二重循环j = i-1# 开始找到正确位置:从小到大排序while j >= 0 and key < arr[j]:arr[j+1] = arr[j] # 向后移动j -= 1# 找到了,交换arr[j+1] = keyreturn arr# 尝试
arr = [64, 34, 25, 12, 22, 11, 90]
print(insertion_sort(arr))

5. 快速排序

5.1 原理

​ 快速排序的主要思想是分治法,将一个大问题分割成小问题,解决小问题后再合并它们的结果。

  1. 选择基准:从数组中选择一个元素作为"基准"
  2. 分区操作:将数组重新排列,所有比基准小的元素放在基准前面,所有比基准大的元素放在基准后面
  3. 递归排序:递归地对基准前后的子数组进行快速排序
  4. 当所有子数组都有序时,整个数组就自然有序了。
  • 时间复杂度:平均O(n log n),最坏O(n²)
  • 空间复杂度:O(log n)
5.2 实现

​ 简单来说就是一个递归算法,既然是递归,肯定得有子问题、边界条件。

  • 边界条件:从上面不难看出,当子数组的长度是1的时候,肯定自然而然有序,就结束了
  • 子问题:对于当前数组的排序,变为基准元素、左子数组、右子数组排序的问题
  • 基准元素:这里我们定义为中间元素为基准元素
# 快速排序
def quick_sort(arr):# 边界条件if len(arr) <= 1:return arr# 基准元素pivot = 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)# 尝试
arr = [64, 34, 25, 12, 22, 11, 90]
print(quick_sort(arr))

​ 而实现从大到小排序的关键就是:

return quick_sort(left) + middle + quick_sort(right)
## 改为
return quick_sort(right) + middle + quick_sort(left)

6. 归并排序

6.1 原理

​ 归并排序是一种基于分治策略的高效排序算法,核心思想是"分而治之":

  1. :将数组递归地分成两半,直到每个子数组只有一个元素
  2. :将两个已排序的子数组合并成一个有序数组
  3. :重复合并过程,直到整个数组有序
  • 时间复杂度:O(n log n)
  • 空间复杂度:O(n):创建了一个result列表存放结果
6.2 实现

​ 这个原理和思路简单易懂,但是实现起来比较复杂。

​ 首先,整体分为两个部分:拆分部分 + 合并部分。

​ 然后,理清整个递归的流程:

  • 边界条件:当划分到只有一个元素的时候,返回当前列表
  • 递归问题:左半部分元素 + 右半部分元素,然后将两者组合

​ 然后,关于组合问题:传入的是left、right两个列表,需要把两者拼接起来,并且大小顺序对应即可。

​ 开始实现:

# 归并排序
def merge_sort(arr):# 整体框架if len(arr) <= 1:return arr# 开始处理mid = 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 += 1# 把两者剩下的部分合并,因为left、right的长度可能不相同,因此while结束后# 可能left、right中还有剩余元素result.extend(left[i:])result.extend(right[j:])return result# 尝试
arr = [64, 34, 25, 12, 22, 11, 90]
print(merge_sort(arr))

​ 实现从大到小的排列,就是改变:

if left[i] < right[j]:
## 变为
if left[i] > right[j]:

7. 堆排序

7.1 原理

​ 堆排序是一种基于二叉堆数据结构的比较排序算法。它结合了插入排序和归并排序的优点:像归并排序一样时间复杂度为O(n log n),像插入排序一样是原地排序。

​ 堆是一种特殊的完全二叉树,满足:

  • 最大堆:每个节点的值都大于或等于其子节点的值
  • 最小堆:每个节点的值都小于或等于其子节点的值

​ 因此,算法流程(构建从小到大):

  1. 构建最大堆:将无序数组构建成最大堆,这样最大的元素就在堆顶(数组的第一个位置)。
  2. 排序:
  • 将堆顶元素(最大值)与堆的最后一个元素交换
  • 堆的大小减1(排除已排序的最大值)
  • 对新的堆顶元素进行"堆化"(下沉操作),恢复最大堆性质
  • 重复步骤1-3,直到堆大小为1
7.2 实现

​ 首先,我们得把数组构建成一个最大堆,即当前结点值大于其所有的子节点值,然后再把最大堆构建为最小堆,即可实现从小到大排序。

​ 首先定义一个函数,去实现最大堆和最小堆,再定义一个函数,去实现二叉树的替换,保证成功构建最大堆。

# 堆排序
def heap_sort(arr):n = len(arr)# 构建最大堆# 从最后一个非叶子节点开始,依次向下调整# [a,b,c,d,e,f,g],变成二叉树,就是# a - b\c# b - d\e# c - f\g# 因此,最后一个非叶子节点就是n//2-1,也就是cfor 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 arrdef heapify(arr,n,i):"""堆化函数:确保以i为根的子树满足最大堆性质n: 堆的大小i: 当前节点的索引"""largest = i      # 初始化最大值为当前节点left = 2 * i + 1  # 左子节点right = 2 * i + 2 # 右子节点# 如果左子节点存在且大于根节点if left < n and arr[left] > arr[largest]:largest = left# 如果右子节点存在且大于当前最大值if right < n and arr[right] > arr[largest]:largest = right# 如果最大值不是当前节点,需要交换并递归堆化if largest != i:arr[i], arr[largest] = arr[largest], arr[i]# 递归堆化受影响的子树heapify(arr, n, largest)# 尝试
arr = [64, 34, 25, 12, 22, 11, 90]
print(heap_sort(arr))

8. 总结

​ 可以多写几次,达到默写的境界,不过建议结合理解算法本身去实现,更容易长久记住。

http://www.dtcms.com/a/414935.html

相关文章:

  • 做兼职去什么网站wordpress 预加载动画
  • XCOSnTh单片机的串口
  • SSR/SSG:Next.js、Nuxt.js的SEO优化与缓存策略
  • 我想做个网站推广怎么做苏州好的网络科技公司
  • 9.27 深度学习9
  • 图数据库:三类图模型核心区别是什么?属性图、资源描述框架和超图。
  • 锥优化介绍(2025年9月27日)
  • 淄博网站制作定制优化怎么在另外一台电脑的浏览器打开自己做的网站地址栏输入什么
  • 做企业网站收费多少钱苏州吴江区城市建设局网站
  • 鸿蒙:PickerDialog 日期选择弹窗实现流程
  • Vue 简介
  • 电商网站项目经验介绍中国企业500强出炉
  • 网站建设 赣icp 南昌成都网站设计哪家比较好
  • Coze源码分析-资源库-删除数据库-后端源码-安全与错误处理
  • .net 程序部署 Docker从零开始实战攻略
  • ps网站轮播图怎么做的宁波外贸公司排名前十
  • wordpress个人博客前台模板泸州网站优化推广
  • OpenCV1
  • 做阿里网站卖东西赚钱智慧团建团员注册入口
  • 拿子游戏
  • 3D 生成模型 开源-混元 3D-Part
  • 了解网站开发的一般过程别人做的网站自己想更新
  • 给周杰伦做网站简易小程序制作
  • 重庆网站设计中心河北手机响应式网站建设设计
  • LBM+FCNN耦合模型:精准高效预测海底裂缝溶解的新工具
  • To B AI 创业黄金打法:从赋能到重塑业务流程
  • 6. 绝对值
  • CTFHub RCE通关笔记5:文件包含 远程包含
  • Redis-实战(短信登录)
  • 网站怎样制作流程网页打不开但是有网什么原因禁用