news 2026/4/23 13:41:35

各种排序算法时间复杂度分析和实现和优势

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
各种排序算法时间复杂度分析和实现和优势

以下是各种排序算法的时间复杂度详细对比:

  1. 比较排序算法

O(n²) 复杂度算法

算法 平均情况 最好情况 最坏情况 空间复杂度 稳定性 说明
冒泡排序 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²) O(n log n) O(n²) O(1) ✗ 改进的插入排序
梳排序 O(n log n) O(n) O(n²) O(1) ✗ 冒泡排序的改进

O(n log n) 复杂度算法

算法 平均情况 最好情况 最坏情况 空间复杂度 稳定性 说明
快速排序 O(n log n) O(n log n) O(n²) O(log n) ✗ 分治,实际最快
归并排序 O(n log n) O(n log n) O(n log n) O(n) ✓ 稳定,适合外排序
堆排序 O(n log n) O(n log n) O(n log n) O(1) ✗ 原地排序,不稳定
TimSort O(n log n) O(n) O(n log n) O(n) ✓ Python/Java内置

  1. 非比较排序算法

线性复杂度算法

算法 平均情况 最好情况 最坏情况 空间复杂度 稳定性 适用条件
计数排序 O(n + k) O(n + k) O(n + k) O(k) ✓ k是数值范围
桶排序 O(n + k) O(n) O(n²) O(n + k) ✓ 数据均匀分布
基数排序 O(d·(n + k)) O(d·(n + k)) O(d·(n + k)) O(n + k) ✓ d是最大位数

  1. 详细分析

快速排序

""" 时间复杂度分析: - 最优情况:每次分区都能均匀划分 T(n) = 2T(n/2) + O(n) = O(n log n) - 最坏情况:每次选到最小或最大值作为枢纽 T(n) = T(n-1) + O(n) = O(n²) - 平均情况:O(n log n) 空间复杂度:递归栈深度 O(log n) """

归并排序

""" 时间复杂度分析: - 分治递归:T(n) = 2T(n/2) + O(n) - 用主定理求解:O(n log n) - 稳定且总是 O(n log n) 空间复杂度:需要额外数组 O(n) """

堆排序

""" 时间复杂度分析: - 建堆:O(n) - 每次堆调整:O(log n) - 总复杂度:O(n) + n·O(log n) = O(n log n) 空间复杂度:原地排序 O(1) """
  1. 实际性能对比

小规模数据 (n < 50)

插入排序 > 选择排序 ≈ 冒泡排序 > 快速排序

原因:插入排序在小数据上常数因子小

中等规模数据 (50 < n < 1000)

快速排序 > 归并排序 > 堆排序 > 希尔排序

大规模数据 (n > 10000)

快速排序 > TimSort > 归并排序 > 堆排序

特定情况

· 基本有序数据:插入排序 O(n),TimSort O(n)
· 范围小的整数:计数排序 O(n + k)
· 外排序(内存不足):归并排序
· 需要稳定性:归并排序、TimSort

  1. Python中的排序实现

内置排序

# Python的sorted()使用TimSortsorted_list=sorted(data)# O(n log n), 稳定# list.sort()也是TimSortdata.sort()# 原地排序

TimSort特点

""" TimSort = 归并排序 + 插入排序 + 优化 1. 将数组分成多个run(有序子序列) 2. 对小的run使用插入排序 3. 使用归并排序合并run 4. 自适应:利用已有顺序 复杂度: - 最好:O(n)(已基本有序) - 平均:O(n log n) - 最坏:O(n log n) - 空间:O(n) """
  1. 各算法代码实现
defbubble_sort(arr):"""冒泡排序 O(n²)"""n=len(arr)foriinrange(n):swapped=Falseforjinrange(0,n-i-1):ifarr[j]>arr[j+1]:arr[j],arr[j+1]=arr[j+1],arr[j]swapped=Trueifnotswapped:breakreturnarrdefselection_sort(arr):"""选择排序 O(n²)"""n=len(arr)foriinrange(n):min_idx=iforjinrange(i+1,n):ifarr[j]<arr[min_idx]:min_idx=j arr[i],arr[min_idx]=arr[min_idx],arr[i]returnarrdefinsertion_sort(arr):"""插入排序 O(n²) - 最好O(n)"""foriinrange(1,len(arr)):key=arr[i]j=i-1whilej>=0andkey<arr[j]:arr[j+1]=arr[j]j-=1arr[j+1]=keyreturnarrdefmerge_sort(arr):"""归并排序 O(n log n)"""iflen(arr)<=1:returnarr mid=len(arr)//2left=merge_sort(arr[:mid])right=merge_sort(arr[mid:])result=[]i=j=0whilei<len(left)andj<len(right):ifleft[i]<=right[j]:result.append(left[i])i+=1else:result.append(right[j])j+=1result.extend(left[i:])result.extend(right[j:])returnresultdefheap_sort(arr):"""堆排序 O(n log n)"""defheapify(arr,n,i):largest=i left=2*i+1right=2*i+2ifleft<nandarr[left]>arr[largest]:largest=leftifright<nandarr[right]>arr[largest]:largest=rightiflargest!=i:arr[i],arr[largest]=arr[largest],arr[i]heapify(arr,n,largest)n=len(arr)# 建堆foriinrange(n//2-1,-1,-1):heapify(arr,n,i)# 一个个取出元素foriinrange(n-1,0,-1):arr[i],arr[0]=arr[0],arr[i]heapify(arr,i,0)returnarrdefcounting_sort(arr):"""计数排序 O(n + k)"""ifnotarr:return[]max_val=max(arr)min_val=min(arr)range_size=max_val-min_val+1count=[0]*range_size output=[0]*len(arr)# 计数fornuminarr:count[num-min_val]+=1# 累加foriinrange(1,range_size):count[i]+=count[i-1]# 输出foriinrange(len(arr)-1,-1,-1):idx=arr[i]-min_val output[count[idx]-1]=arr[i]count[idx]-=1returnoutput
  1. 算法选择指南

根据需求选择:

· 通用排序:快速排序或TimSort
· 需要稳定:归并排序或TimSort
· 原地排序(内存少):堆排序或快速排序
· 小数据量:插入排序
· 整数,范围小:计数排序
· 数据基本有序:插入排序或TimSort
· 链表结构:归并排序

根据数据特征:

数据特征 | 推荐算法 ----------------------|------------ 随机 | 快速排序 基本有序 | 插入排序/TimSort 范围小的整数 | 计数排序 需要稳定排序 | 归并排序/TimSort 内存受限 | 堆排序 分布式/外排序 | 归并排序
  1. 性能测试示例
importtimeimportrandomimportmatplotlib.pyplotaspltdefbenchmark_algorithms():"""性能基准测试"""algorithms={'冒泡排序':bubble_sort,'选择排序':selection_sort,'插入排序':insertion_sort,'快速排序':quick_sort_simple,'归并排序':merge_sort,'堆排序':heap_sort,}sizes=[100,500,1000,5000,10000]results={name:[]fornameinalgorithms}forsizeinsizes:arr=random.sample(range(size*10),size)forname,funcinalgorithms.items():ifsize>5000andnamein['冒泡排序','选择排序','插入排序']:# O(n²)算法太慢,跳过results[name].append(None)continuearr_copy=arr.copy()start=time.time()func(arr_copy)end=time.time()results[name].append(end-start)# 可视化plt.figure(figsize=(12,6))forname,timesinresults.items():valid_times=[tfortintimesiftisnotNone]valid_sizes=[sizes[i]fori,tinenumerate(times)iftisnotNone]ifvalid_times:plt.plot(valid_sizes,valid_times,marker='o',label=name)plt.xlabel('数据量')plt.ylabel('时间 (秒)')plt.title('排序算法性能对比')plt.legend()plt.grid(True)plt.show()# benchmark_algorithms() # 取消注释运行测试

这个总结应该能帮助你根据具体情况选择合适的排序算法!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/18 2:55:54

【Java】ThreadLocal源码解析

一、谈谈对ThreadLocal的理解以及它与synchronized的区别#一句话总结&#xff1a; ThreadLocal提供线程局部变量&#xff0c;通过线程隔离机制&#xff0c;确保每个线程拥有变量的独立副本&#xff0c;实现了“以空间换时间”的线程安全。与 synchronized的区别&#xff1a;syn…

作者头像 李华
网站建设 2026/4/23 12:45:11

通过企业微信ipad协议接口查询群成员信息

请求方式POSTContentType:”application/json”参数参数名必选类型说明uuid是String每个实例的唯一标识&#xff0c;根据uuid操作具体企业微信请求示例{"uuid":"3240fde0-45e2-48c0-90e8-cb098d0ebe43","roomid":1069XXXX5016166}返回示例{"…

作者头像 李华
网站建设 2026/4/17 14:50:07

JSP中如何设计大文件上传的加密存储方案?

我&#xff0c;一个负责过30企业级文件传输项目的上海IT人&#xff0c;想和你聊聊这个100G大文件传输的落地方案 先抛结论&#xff1a;这事儿能成&#xff0c;但得用“定制化研发成熟组件适配”的组合拳。作为公司项目负责人&#xff0c;我刚带着团队啃完类似需求&#xff08;…

作者头像 李华
网站建设 2026/4/17 0:24:27

网页前端如何利用JS实现100G文件分块上传?

武汉光谷XX软件公司大文件传输组件选型与自研方案 一、项目背景与需求分析 作为武汉光谷地区专注于软件研发的高新技术企业&#xff0c;我司长期服务于政府和企业客户&#xff0c;在政务信息化、企业数字化转型等领域积累了丰富的经验。当前&#xff0c;我司核心产品面临大文…

作者头像 李华
网站建设 2026/4/23 13:35:55

数学建模优秀论文算法-高斯过程回归

高斯过程回归&#xff08;GPR&#xff09;小白入门教程 0. 引言&#xff1a;为什么需要高斯过程回归&#xff1f; 在机器学习中&#xff0c;回归任务的目标是用已知数据拟合一个函数&#xff0c;预测新输入的输出。传统方法&#xff08;如线性回归、多项式回归&#xff09;存在…

作者头像 李华
网站建设 2026/4/23 10:44:20

数学建模优秀论文算法-深度生存网络

深度生存网络入门教程&#xff1a;从生存分析到端到端建模 引言 在医疗、金融、工业等领域&#xff0c;我们常关注**“事件发生时间”**问题&#xff1a; 医疗&#xff1a;癌症患者的生存期&#xff08;“多久会去世”&#xff09;&#xff1b;金融&#xff1a;客户的违约时间&…

作者头像 李华