Python常用排序算法

1. 冒泡排序

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

def bubble_sort(arr):# 遍历所有数组元素for i in range(len(arr)):# 最后i个元素是已经排序好的for j in range(0, len(arr)-i-1):# 如果当前元素大于下一个元素,则交换位置if arr[j] > arr[j+1]:arr[j], arr[j+1] = arr[j+1], arr[j]return arrarr = [11, 32, 21, 67, 54, 19]
sorted_arr = bubble_sort(arr)
print("排序后为:", sorted_arr)

输出结果:
排序后为: [11, 19, 21, 32, 54, 67]

复杂度分析

  1. 时间复杂度:
  • 最坏情况:O(n2)(完全逆序)
  • 最好情况:O(n)
  • 平均情况:O(n2)
  1. 空间复杂度:O(1)(原地排序)

2. 选择排序

选择排序是一种简单直观的排序算法,它的工作原理是每次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排序完毕。

def select_sort(arr):# 遍历所有数组元素for i in range(len(arr)):# 找到剩余未排序部分的最小元素索引min_index = ifor j in range(i+1, len(arr)):if arr[j] < arr[min_index]:min_index = j# 将找到的最小元素与第i个位置的元素交换arr[i], arr[min_index] =  arr[min_index], arr[i]return arrarr = [11, 32, 21, 67, 54, 19]
sorted_arr = select_sort(arr)
print("排序后为:", sorted_arr)

输出结果:
排序后为: [11, 19, 21, 32, 54, 67]

复杂度分析

  1. 时间复杂度:O(n2)
  2. 空间复杂度:O(1)(原地排序)

3. 插入排序

插入排序是一种简单直观的排序算法,它的工作原理是通过构建有序序列,在已排序序列中从后向前扫描,找到相应位置并插入。

def insert_sort(arr):# 遍历从1到倒数第二个元素for i in range(1, len(arr)):# 当前需要插入的元素key = arr[i]# 已排序部分的最后一个元素索引j = i - 1# 将arr[i]与已排序部分的元素逐个比较,如果比key大则后移一位while j >= 0 and key < arr[j]:arr[j + 1] = arr[j]j -= 1# 找到合适位置,插入keyarr[j + 1] = keyreturn arrarr = [11, 32, 21, 67, 54, 19]
sorted_arr = insert_sort(arr)
print("排序后为:", sorted_arr)

输出结果:
排序后为: [11, 19, 21, 32, 54, 67]

复杂度分析

  1. 时间复杂度:
  • 最坏情况:O(n2)(当数组是逆序时)
  • 最好情况:O(n)(当数组已经有序时)
  • 平均情况:O(n2)
  1. 空间复杂度:O(1)(原地排序)

4. 快速排序

快速排序是一种高效的排序算法,采用分治法策略。首先任意选取一个元素作为基准数据,将待排序列表中的数据分割成独立的两部分,比基准数据小的放在它左边,比基准数据大的放在它右边,此时第一轮数据排序完成。然后再按照此方法对两边的数据分别进行分割,直至被分割的数据只有一个或者零个时,递归结束。

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 = [11, 32, 21, 67, 54, 19]
sorted_arr = quick_sort(arr)
print("排序后为:", sorted_arr)

输出结果:
排序后为: [11, 19, 21, 32, 54, 67]

复杂度分析

  1. 时间复杂度:
  • 最坏情况:O(n2)(当分区极度不平衡时)
  • 最好情况:O(n log n)
  • 平均情况:O(n log n)
  1. 空间复杂度:O(n)(创建了新的列表)

5. 归并排序

归并排序是一种基于分治策略的高效排序算法,将数组不断地分成两半,然后递归地对两半进行排序,最后将排序好的两半合并在一起。

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# 添加剩余元素result.extend(left[i:])result.extend(right[j:])return resultarr = [38, 27, 43, 3, 9, 82, 10]
sorted_arr = merge_sort(arr)
print("排序后为:", sorted_arr)

输出结果:
排序后为: [3, 9, 10, 27, 38, 43, 82]

复杂度分析

  1. 时间复杂度:O(n log n)
  2. 空间复杂度: O(n)(需要额外空间存储临时数组)

6. 堆排序

堆排序是一种基于二叉堆数据结构的高效排序算法。堆是一种特殊的完全二叉树,其中每个父节点的值都大于或等于其子节点的值(称为最大堆)或每个父节点的值都小于或等于其子节点的值(称为最小堆)。

import heapqdef heap_sort(arr):# 构建最小堆heapq.heapify(arr)return [heapq.heappop(arr) for _ in range(len(arr))]arr = [12, 11, 15, 3, 21, 9]
sorted_arr = heap_sort(arr)
print("排序后为:", sorted_arr)

输出结果:
排序后为: [3, 9, 11, 12, 15, 21]

复杂度分析

  1. 时间复杂度:
  • 建堆过程:O(n)
  • 每次堆化:O(log n)
  • 总体时间复杂度:O(n log n)
  1. 空间复杂度: O(1)(原地排序)

7. 计数排序

计数排序是一种非比较排序算法,适用于对一定范围内的整数进行排序。它统计数组中每个元素出现的次数,然后根据统计结果将元素放回正确的位置。

def count_sort(arr):if len(arr) == 0:return arr# 找到数组中的最大值和最小值max_val = max(arr)min_val = min(arr)# 创建计数数组,初始化为0count = [0] * (max_val - min_val + 1)# 统计每个元素出现的次数for num in arr:count[num - min_val] += 1# 重建排序后的数组sorted_arr = []for i in range(len(count)):sorted_arr.extend([i + min_val] * count[i])return sorted_arrarr = [4, 2, 5, 1, 8]
sorted_arr = count_sort(arr)
print("排序后为:", sorted_arr)

输出结果:
排序后为: [1, 2, 4, 5, 8]

复杂度分析

  1. 时间复杂度:O(n+k),其中n是元素数量,k是数据范围
  2. 空间复杂度:O(n+k)

8. 基数排序

基数排序是一种非比较型整数排序算法,它通过将整数按位切割成不同的数字,然后按每个位数分别比较排序。基数排序可以采用最低位优先(LSD)或最高位优先(MSD)两种方式。

def radix_sort(arr):# 找到数组中的最大数,确定排序的轮数max_num = max(arr)# 从个位开始exp = 1while max_num // exp > 0:counting_sort_by_digit(arr, exp)exp *= 10return arrdef counting_sort_by_digit(arr, exp):n = len(arr)output = [0] * ncount = [0] * 10# 统计当前位数的数字出现次数for num in arr:digit = (num // exp) % 10count[digit] += 1# 计算累加计数for i in range(1, 10):count[i] += count[i-1]# 反向填充输出数组(保证稳定性)for i in range(n-1, -1, -1):digit = (arr[i] // exp) % 10output[count[digit] - 1] = arr[i]count[digit] -= 1# 将排序结果复制回原数组for i in range(n):arr[i] = output[i]arr = [170, 45, 75, 90, 802, 24, 2, 66]
sorted_arr = radix_sort(arr)
print("排序后为:", sorted_arr)

输出结果:
排序后为: [2, 24, 45, 66, 75, 90, 170, 802]

复杂度分析

  1. 时间复杂度:O(d*(n+k)),其中d是最大数字的位数,n是元素数量,k是基数
  2. 空间复杂度:O(n+k)

9. 桶排序

桶排序是一种分布式排序算法,它将元素分到有限数量的桶里,每个桶再分别排序。

def bucket_sort(arr, bucket_size=5):if len(arr) == 0:return arr# 找到最大值和最小值max_val = max(arr)min_val = min(arr)# 计算桶的数量bucket_count = (max_val - min_val) // bucket_size + 1buckets = [[] for _ in range(bucket_count)]# 将元素分配到各个桶中for num in arr:index = (num - min_val) // bucket_sizebuckets[index].append(num)# 对每个桶进行排序sorted_arr = []for bucket in buckets:# 使用内置的sorted函数sorted_arr.extend(sorted(bucket))return sorted_arrarr = [29 ,25, 13, 21, 8, 43]
sorted_arr = bucket_sort(arr)
print("排序后为:", sorted_arr)

输出结果:
排序后为: [8, 13, 21, 25, 29, 43]

复杂度分析

  1. 时间复杂度:
  • 平均情况:O(n+k),其中k是桶的数量
  • 最坏情况:O(n2)(当所有元素都分配到同一个桶中)
  1. 空间复杂度:O(n+k)

10. 希尔排序

希尔排序是插入排序的一种高效改进版本,也称为缩小增量排序。它通过将原始列表分割成多个子列表来进行插入排序,随着算法的进行,子列表的长度逐渐增大,最终整个列表变为一个子列表完成排序。

def shell_sort(arr):n = len(arr)# 初始间隔(gap)设置为数组长度的一半gap = n // 2while gap > 0:# 对各个间隔分组进行插入排序for i in range(gap, n):temp = arr[i]j = i# 对子列表进行插入排序while j >= gap and arr[j - gap] > temp:arr[j] = arr[j - gap]j -= gaparr[j] = temp# 缩小间隔gap = gap // 2return arrarr = [9 , 8, 3, 6, 5, 7, 1]
sorted_arr = shell_sort(arr)
print("排序后为:", sorted_arr)

输出结果:
排序后为: [1, 3, 5, 6, 7, 8, 9]

复杂度分析

  1. 时间复杂度:
  • 平均情况:O(n1.3)到O(n1.5)
  • 最坏情况:O(n*n)
  • 最好情况:O(n log n)
  1. 空间复杂度:O(1)(原地排序)

11. 拓扑排序

拓扑排序是针对有向无环图的线性排序算法,使得对于图中的每一条有向边(u, v),u在排序中总是位于v的前面。

from collections import dequedef topo_sort_kahn(graph):# 计算所有节点的入度in_degree = {node: 0 for node in graph}for node in graph:for neighbor in graph[node]:in_degree[neighbor] += 1# 初始化队列,将所有入度为0的节点加入队列queue = deque([node for node in graph if in_degree[node] == 0])topo_order = []while queue:current = queue.popleft()topo_order.append(current)# 减少所有邻居的入度for neighbor in graph[current]:in_degree[neighbor] -= 1# 如果邻居的入度变为0,加入队列if in_degree[neighbor] == 0:queue.append(neighbor)# 检查是否所有节点都被排序(无环)if len(topo_order) == len(graph):return topo_orderelse:return []  # 图中存在环,无法进行拓扑排序
# 定义有向无环图(邻接表表示)
graph = {'A': ['B', 'C'],'B': ['D', 'E'],'C': ['F'],'D': [],'E': ['F'],'F': []
}print("Kahn算法拓扑排序结果:", topo_sort_kahn(graph))

输出结果:
Kahn算法拓扑排序结果: [‘A’, ‘B’, ‘C’, ‘D’, ‘E’, ‘F’]

复杂度分析

  1. 时间复杂度:O(V+E),其中V是顶点数,E是边数
  2. 空间复杂度:O(V)(存储入度或递归栈)

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

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

相关文章

解锁塔能科技,开启工厂绿色转型与可持续发展双引擎

在全球积极推进可持续发展的大背景下&#xff0c;能源的高效利用与节能减排&#xff0c;已成为各行各业迈向高质量发展进程中无法回避的核心任务。工厂作为能源消耗大户与污染排放重点源头&#xff0c;其绿色转型迫在眉睫&#xff0c;这不仅关乎企业自身的长远发展&#xff0c;…

Spring Boot 线程池配置详解

Spring Boot 线程池配置详解 一、核心配置参数及作用 基础参数核心线程数 (corePoolSize)‌ 作用‌:线程池中始终保持存活的线程数量,即使空闲也不回收‌。 建议‌:根据任务类型设定(如 I/O 密集型任务可设为 CPU 核心数 2)‌。 最大线程数 (maxPoolSize)‌ 作用‌:…

入侵检测系统(IDS)和入侵防御系统(IPS)有啥区别?

入侵检测系统&#xff08;IDS&#xff09;和入侵防御系统&#xff08;IPS&#xff09;是网络安全中的两种关键技术&#xff0c;它们的核心区别在于 检测后的响应方式 和 部署位置。以下是详细对比&#xff1a; 1. 核心功能 - IDS&#xff08;入侵检测系统&#xff09; - 仅监…

【MySQL 数据库】数据表的操作

&#x1f525;博客主页&#x1f525;&#xff1a;【 坊钰_CSDN博客 】 欢迎各位点赞&#x1f44d;评论✍收藏⭐ 目录 1. 表的查看 1.1 语法 2. 表的创建 2.1 语法 2.2 练习 3. 查看表结构 3.1 语法 3.2 示例 4. 表的修改 4.1 语法 4.2 示例操作 4.2.1 向表中添加字段…

sqli-labs靶场 less5

文章目录 sqli-labs靶场less 5 报错注入 sqli-labs靶场 每道题都从以下模板讲解&#xff0c;并且每个步骤都有图片&#xff0c;清晰明了&#xff0c;便于复盘。 sql注入的基本步骤 注入点注入类型 字符型&#xff1a;判断闭合方式 &#xff08;‘、"、’、“”&#xf…

C# 状态模式深度解析:构建灵活的状态驱动系统

一、状态模式概述 状态模式&#xff08;State Pattern&#xff09;是一种行为型设计模式&#xff0c;它允许对象在其内部状态改变时改变其行为&#xff0c;使对象看起来像是修改了它的类。这种模式将特定状态相关的行为局部化&#xff0c;并且将不同状态的行为分割开来。 状态…

vue实现二维码生成器和解码器

vue实现二维码生成器和解码器 1.生成基本二维码&#xff1a;根据输入的value生成二维码。 2.可定制尺寸&#xff1a;通过size调整大小。 3.颜色和背景色&#xff1a;设置二维码颜色和背景。 4.静区&#xff08;quiet zone&#xff09;支持&#xff1a;通过quietZone调整周围的…

Nacos:Nacos服务注册与服务发现超详细的源码解析(二)

&#x1fa81;&#x1f341; 希望本文能给您带来帮助&#xff0c;如果有任何问题&#xff0c;欢迎批评指正&#xff01;&#x1f405;&#x1f43e;&#x1f341;&#x1f425; 文章目录 一、背景二、环境与依赖三、服务注册与服务发现总流程图四、服务注册源码4.1 客户端4.1.1…

ECMAScript 6 新特性(二)

ECMAScript 6 新特性&#xff08;二&#xff09; ECMAScript 6 新特性&#xff08;一&#xff09; ECMAScript 6 新特性&#xff08;二&#xff09;&#xff08;本文&#xff09; ECMAScript 7~10 新特性 1. 生成器 生成器函数是 ES6 提供的一种解决异步编程方案&#xff0c;一…

深入理解 RxSwift 中的 Driver:用法与实践

目录 前言 一、什么是Driver 1.不会发出错误 2.主线程保证 3.可重放 4.易于绑定 二、Driver vs Observable 三、使用场景 1.绑定数据到UI控件 2.响应用户交互 3.需要线程安全的逻辑 4.如何使用Driver? 1.绑定文本输入到Label 2.处理按钮点击事件 3.从网络请求…

Linux自行实现的一个Shell(15)

文章目录 前言一、头文件和全局变量头文件全局变量 二、辅助函数获取用户名获取主机名获取当前工作目录获取最后一级目录名生成命令行提示符打印命令行提示符 三、命令处理获取用户输入解析命令行执行外部命令 四、内建命令添加环境变量检查和执行内建命令 五、初始化初始化环境…

RocketMQ和kafka 的区别

一、数据可靠性与容错机制 数据可靠性 RocketMQ支持同步刷盘和同步复制&#xff0c;确保消息写入磁盘后才返回确认&#xff0c;单机可靠性高达10个9&#xff0c;即使操作系统崩溃也不会丢失数据。而Kafka默认采用异步刷盘和异步复制&#xff0c;虽然吞吐量高&#xff0c;但极端…

在 openEuler 24.03 (LTS) 操作系统上添加 ollama 作为系统服务的步骤

以下是在 openEuler 操作系统上添加 ollama 作为系统服务的步骤&#xff1a; 创建 systemd 服务文件 sudo vi /etc/systemd/system/ollama.service将以下内容写入服务文件&#xff08;按需修改参数&#xff09;&#xff1a; [Unit] DescriptionOllama Service Afternetwork.…

光谱相机的关键技术参数

光谱相机的关键技术参数直接影响其数据获取能力和应用场景适配性。以下是核心参数的详细解析&#xff0c;涵盖光谱性能、空间性能、硬件性能及环境适应性&#xff1a; 一、光谱性能参数‌ ‌1. 光谱范围&#xff08;Spectral Range&#xff09;‌ ‌定义‌&#xff1a;相机可…

ARM内核与寄存器

ARM内核与寄存器详解 目录 ARM架构概述ARM处理器模式 Cortex-M3内核的处理器模式Cortex-A系列处理器模式 ARM寄存器集 通用寄存器程序计数器(PC)链接寄存器(LR)堆栈指针(SP)状态寄存器(CPSR/SPSR) 协处理器寄存器NEON和VFP寄存器寄存器使用规范常见ARM指令与寄存器操作 ARM架…

Git 拉取时常见冲突及解决方法总结

Git 拉取时常见冲突及解决方法总结 一、常见错误场景1. 本地修改与远程修改冲突解决方法 2. 未跟踪文件与远程文件冲突解决方法 3. 子模块权限问题解决方法 二、总结 在日常开发中&#xff0c;使用 Git 进行团队协作和代码管理时&#xff0c;经常会遇到拉取代码&#xff08;git…

深度学习、图像算法学习记录

深度学习加速 综述文档&#xff1a; https://chenzomi12.github.io/02Hardware01Foundation/02ArchSlim.html winograd: https://zhuanlan.zhihu.com/p/260109670 ncnn 1.修改模型结构&#xff0c;优化模型内存访问次数&#xff0c;加速。 VGG 和 InceptionNet &#xff1a; …

Java中的Exception和Error有什么区别?还有更多扩展

概念 在Java中&#xff0c;Exception和Error都是Throwable的子类&#xff0c;用于处理程序中的错误和异常情况。 然而&#xff0c;它们在用途和处理方式上有显著的不同&#xff1a; Exception&#xff1a; 用于表示程序在正常运行过程中可能出现的错误&#xff0c;如文件未找…

文章记单词 | 第26篇(六级)

一&#xff0c;单词释义 actor&#xff1a;名词&#xff0c;演员mask&#xff1a;名词&#xff0c;面具&#xff1b;口罩&#xff1b;遮盖物&#xff1b;动词&#xff0c;掩饰&#xff1b;戴面具&#xff1b;遮盖construct&#xff1a;动词&#xff0c;建造&#xff1b;构造&a…

LeetCode算法题(Go语言实现)_38

题目 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 一、代码实现 type TreeNode struct {Val intLeft *TreeNodeRight *TreeNode }func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {if root nil || root p || root q {return root}left : lowes…