首页/新闻资讯/正文详情

常见排序算法详解:从基础到高级实现

发布时间:2026/11/5 22:36:41 来源:云帆数科 栏目:资讯中心
常见排序算法详解:从基础到高级实现
1. 排序算法基础概念排序算法是计算机科学中最基础也是最重要的算法类别之一。简单来说排序算法就是将一组数据按照特定顺序通常是升序或降序重新排列的过程。在计算机程序中排序算法的应用无处不在从简单的数据展示到复杂的数据库查询优化都离不开高效的排序算法。排序算法主要可以分为两大类比较排序和非比较排序。比较排序是通过比较元素之间的大小关系来决定它们的相对顺序而非比较排序则不通过比较来决定元素的顺序。常见的比较排序算法包括冒泡排序、选择排序、插入排序、归并排序、快速排序等而非比较排序则包括计数排序、基数排序和桶排序等。2. 常见排序算法详解2.1 冒泡排序冒泡排序是最简单的排序算法之一。它的基本思想是通过不断比较相邻元素并交换它们的位置使得较大的元素逐渐冒泡到数组的末端。def bubble_sort(arr): n len(arr) for i in range(n): # 每次遍历后最大的元素已经冒泡到最后 for j in range(0, n-i-1): if arr[j] arr[j1]: arr[j], arr[j1] arr[j1], arr[j] return arr冒泡排序的时间复杂度为O(n²)空间复杂度为O(1)。虽然实现简单但对于大规模数据排序效率较低。2.2 选择排序选择排序的工作原理是每次从未排序的部分中选择最小或最大的元素放到已排序部分的末尾。def selection_sort(arr): n len(arr) for i in range(n): min_idx i for j in range(i1, n): if arr[j] arr[min_idx]: min_idx j arr[i], arr[min_idx] arr[min_idx], arr[i] return arr选择排序的时间复杂度也是O(n²)但相比冒泡排序它的交换次数更少在某些情况下性能略好。2.3 插入排序插入排序的思想是将数组分为已排序和未排序两部分每次从未排序部分取出一个元素插入到已排序部分的适当位置。def insertion_sort(arr): for i in range(1, len(arr)): key arr[i] j i-1 while j 0 and key arr[j]: arr[j1] arr[j] j - 1 arr[j1] key return arr插入排序在小型数据集或基本有序的数据集上表现良好时间复杂度为O(n²)但在最好情况下可以达到O(n)。3. 高级排序算法3.1 归并排序归并排序采用分治策略将数组分成两半分别排序后再合并。def merge_sort(arr): if len(arr) 1: mid len(arr)//2 L arr[:mid] R arr[mid:] merge_sort(L) merge_sort(R) i j k 0 while i len(L) and j len(R): if L[i] R[j]: arr[k] L[i] i 1 else: arr[k] R[j] j 1 k 1 while i len(L): arr[k] L[i] i 1 k 1 while j len(R): arr[k] R[j] j 1 k 1 return arr归并排序的时间复杂度为O(n log n)空间复杂度为O(n)是一种稳定的排序算法。3.2 快速排序快速排序也是基于分治思想通过选择一个基准元素将数组分成两部分一部分小于基准一部分大于基准然后递归地对两部分进行排序。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)快速排序的平均时间复杂度为O(n log n)但在最坏情况下会退化到O(n²)。通过合理选择基准可以避免最坏情况的发生。4. 非比较排序算法4.1 计数排序计数排序不是通过比较来决定元素顺序而是通过统计每个元素的出现次数来实现排序。def counting_sort(arr): max_val max(arr) count [0] * (max_val 1) for num in arr: count[num] 1 sorted_arr [] for i in range(len(count)): sorted_arr.extend([i] * count[i]) return sorted_arr计数排序的时间复杂度为O(n k)其中k是数据的范围。它适用于数据范围不大且分布均匀的情况。4.2 基数排序基数排序是按照低位先排序然后收集再按照高位排序然后再收集依次类推直到最高位。def counting_sort_for_radix(arr, exp): n len(arr) output [0] * n count [0] * 10 for i in range(n): index arr[i] // exp count[index % 10] 1 for i in range(1, 10): count[i] count[i-1] i n - 1 while i 0: index arr[i] // exp output[count[index % 10] - 1] arr[i] count[index % 10] - 1 i - 1 for i in range(n): arr[i] output[i] def radix_sort(arr): max_val max(arr) exp 1 while max_val // exp 0: counting_sort_for_radix(arr, exp) exp * 10 return arr基数排序的时间复杂度为O(d(n k))其中d是数字的位数k是基数通常是10。它特别适合对大量数字进行排序。5. 排序算法的比较与选择5.1 时间复杂度比较算法最好情况平均情况最坏情况空间复杂度稳定性冒泡排序O(n)O(n²)O(n²)O(1)稳定选择排序O(n²)O(n²)O(n²)O(1)不稳定插入排序O(n)O(n²)O(n²)O(1)稳定归并排序O(n log n)O(n log n)O(n log n)O(n)稳定快速排序O(n log n)O(n log n)O(n²)O(log n)不稳定计数排序O(n k)O(n k)O(n k)O(n k)稳定基数排序O(d(n k))O(d(n k))O(d(n k))O(n k)稳定5.2 如何选择合适的排序算法选择排序算法时需要考虑以下几个因素数据规模对于小规模数据简单的O(n²)算法可能比复杂的O(n log n)算法更高效。数据特性如果数据基本有序插入排序会表现很好如果数据范围不大计数排序或基数排序可能更合适。内存限制归并排序需要额外空间而快速排序和堆排序是原地排序。稳定性需求某些应用场景要求排序是稳定的相等元素的相对位置不变。实现复杂度简单的算法更容易实现和维护。在实际应用中编程语言的内置排序函数通常是经过高度优化的混合算法在大多数情况下都是最佳选择。例如Python的sorted()函数使用的是Timsort算法它是归并排序和插入排序的混合体具有很好的性能特性。6. 排序算法的实际应用排序算法在计算机科学和软件开发中有着广泛的应用数据库系统索引创建、查询优化等都需要高效的排序算法。搜索引擎搜索结果需要按照相关性或其他指标排序。数据分析数据预处理和统计分析经常需要对数据进行排序。操作系统进程调度、文件系统管理等都需要排序操作。图形学深度排序、可见性判断等图形算法依赖排序。机器学习特征选择、模型评估等步骤可能需要排序。理解不同排序算法的特性和适用场景能够帮助我们在实际开发中做出更合理的选择提高程序的性能和效率。7. 排序算法的优化与实践技巧7.1 混合排序策略在实际应用中常常会结合多种排序算法的优点。例如当递归到小规模子问题时切换到插入排序在快速排序中当分区大小小于某个阈值时使用插入排序结合归并排序和插入排序的Timsort算法7.2 并行排序现代计算机多核CPU的普及使得并行排序成为可能。许多排序算法可以并行化归并排序可以并行地对左右两部分进行排序快速排序分区后可以并行处理两个子数组基数排序每个位数的排序可以并行处理7.3 特定场景优化针对特定数据特征可以进行优化对于几乎有序的数据插入排序和冒泡排序可以有接近O(n)的性能对于包含大量重复元素的数据三向切分的快速排序更高效对于外部排序数据量大于内存需要使用归并排序的变种8. 常见问题与解决方案8.1 为什么我的快速排序在某些情况下很慢快速排序的性能依赖于基准的选择。如果基准选择不当如总是选择第一个或最后一个元素在已排序或逆序数据上会退化到O(n²)。解决方案随机选择基准使用三数取中法选择第一个、中间和最后一个元素的中位数当递归深度过大时切换到堆排序8.2 如何选择稳定的排序算法如果需要保持相等元素的相对顺序可以选择以下稳定排序算法冒泡排序插入排序归并排序计数排序基数排序8.3 如何处理大规模数据的排序对于无法全部装入内存的大规模数据使用外部排序算法通常是基于归并排序的变种将数据分割成可以装入内存的块分别排序后合并考虑使用数据库系统它们已经优化了大规模数据的排序8.4 如何验证排序算法的正确性可以通过以下方式验证对小型测试用例手动验证检查排序后的数组是否单调非递减或非递增验证排序前后数组的元素是否相同无丢失或新增使用随机生成的大量测试用例进行压力测试9. 排序算法的扩展学习9.1 可视化工具使用排序算法可视化工具可以更直观地理解不同算法的工作原理Visualgo.netAlgorithm VisualizerSorting.at9.2 进阶算法掌握基础排序算法后可以学习更高级的排序技术内省排序Introsort结合快速排序、堆排序和插入排序TimsortPython和Java使用的混合排序算法块排序Block sort适合外部排序的算法并行排序算法的实现9.3 算法竞赛中的应用在编程竞赛中排序算法常用于预处理数据以便更高效地处理贪心算法的实现解决与逆序对相关的问题离散化处理理解排序算法不仅是编程基础也是培养算法思维的重要一步。通过不断实践和优化可以深入理解不同算法的特性和适用场景在实际开发中做出更明智的选择。

相关推荐

AI测试工具演进与主流平台深度评测
AI测试工具演进与主流平台深度评测

1. AI测试工具的发展历程作为一名在软件测试领域摸爬滚打多年的老兵,我亲眼见证了测试工具从"人工智障"到"真香"的进化过程。记得2015年第一次接触所谓的"智能测试工具"时,那些工具只能执行简单的录制回放,稍微… · 2026/11/5 14:32:14

LLM Wiki:超长上下文、Agentic检索与本体建模的三重协同
LLM Wiki:超长上下文、Agentic检索与本体建模的三重协同

1. 这不是又一个RAG套壳项目:从“LLM Wiki”热词爆发看知识架构的范式迁移最近两周,朋友圈、技术群、甚至非AI圈的朋友都在问:“LLM Wiki是什么?”——不是某个新开源项目的名字,也不是某家公司的新产品代号&#xff0… · 2026/11/5 4:27:51

龙珠超98话战斗艺术与角色成长解析
龙珠超98话战斗艺术与角色成长解析

1. 龙珠超第98话深度解析:战斗艺术与角色成长作为一名资深龙珠迷,我最近重新观看了《龙珠超》第98话,发现这一集在战斗设计和角色塑造上有着许多值得玩味的细节。虽然标题"dragonballsuper_098-2"看起来只是一个简单的编号&#xf… · 2026/11/5 20:16:49

EasyU优启通PE维护盘实战指南:制作、启动与核心操作全解析
EasyU优启通PE维护盘实战指南:制作、启动与核心操作全解析

1. 为什么一个PE维护盘值得单独拿出来聊装系统、修引导、救数据、清病毒,这些活儿但凡干过几次的人都知道,真正决定效率的往往不是你手速多快,而是手边那套PE环境靠不靠谱。EasyU(圈内习惯叫优启通)就是在这个场景下被… · 2026/11/5 16:49:35

Rust原来很简单二:所有权系统
Rust原来很简单二:所有权系统

Part 2 核心篇 —— 所有权系统 本篇覆盖 第 6 ~ 10 章:所有权、借用与引用、生命周期、字符串与切片、内存模型。 ⚠️ 这是全书最重要的一篇。 把它吃透,Rust 从此“很简单”;跳过它,你会处处碰壁。请慢下来,动手敲每一段代码。 第 6 章 所有权:Rust 的第一性原理 6… · 2026/11/5 16:26:08

基于Hadoop+Spark的民宿智能推荐系统设计与实现
基于Hadoop+Spark的民宿智能推荐系统设计与实现

1. 项目概述:大数据时代的民宿智能推荐这个毕业设计项目融合了当前大数据领域最主流的技术栈,构建了一个完整的民宿推荐系统解决方案。作为一名长期从事大数据系统开发的工程师,我认为这个选题非常贴合实际应用场景——随着旅游业的复苏和共享… · 2026/11/5 14:59:25

ADS122U04IPWR+STM32F427ZI工业级温度测量信号链设计
ADS122U04IPWR+STM32F427ZI工业级温度测量信号链设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 14:10:41

UART接口24位ADC搭配RS485,解决远距离温度监控难题
UART接口24位ADC搭配RS485,解决远距离温度监控难题

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 14:10:41

UART接口24位ADC搭配PIC18F46K22的RTD与热电偶测温实践
UART接口24位ADC搭配PIC18F46K22的RTD与热电偶测温实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 14:10:41

双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:27:59

STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:28:03

DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:28:07

多智能体协作系统架构设计与实践优化
多智能体协作系统架构设计与实践优化

1. 多智能体协作系统的时代背景2017年Transformer架构的诞生彻底改变了人工智能的发展轨迹。当行业还沉浸在单一大模型带来的性能突破时,Anthropic的研究团队已经将目光投向了更前沿的领域——如何让多个智能体通过协作产生超越单体能力的系统智能。这就像交响乐团中… · 2026/11/5 0:00:39

大模型系统性入门实战指南:从原理到部署微调的全链路路线
大模型系统性入门实战指南:从原理到部署微调的全链路路线

提到大模型的系统性入门,我先说个结论:这事真不难,难的是资料太散、路线太多,今天这个框架明天那个工具,新人很容易在“收藏夹吃灰”和“教程看到一半放弃”之间反复横跳。市面上关于大模型的内容少说有几十万篇&#… · 2026/11/5 0:00:39

鸿蒙文件系统沙箱机制解析与开发实践
鸿蒙文件系统沙箱机制解析与开发实践

1. 鸿蒙文件系统沙箱机制深度解析作为一名从Android转向鸿蒙开发的工程师,我深刻体会到文件系统访问是迁移过程中最先遇到的"拦路虎"。在Android上运行良好的文件读写代码,在鸿蒙真机环境却频频出现文件写入后神秘消失或直接抛出权限拒绝错误的… · 2026/11/5 0:00:39

双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:27:59

STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:28:03

DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:28:07

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码