Python 算法高级篇:归并排序的优化与外部排序
Python 算法高级篇:归并排序的优化与外部排序
- 引言
- 1. 归并排序的基本原理
- 2. 归并排序的优化
- 2.1 自底向上的归并排序
- 2.2 最后优化
- 3. 外部排序
- 4. 性能比较
- 5. 结论
引言
在计算机科学中,排序是一项基本的任务,而归并排序( Merge Sort )是一种著名的排序算法,它具有稳定性和良好的时间复杂度。本文将介绍归并排序的基本原理,然后深入探讨如何进行优化以及如何应用归并排序进行外部排序。
😃😄 ❤️ ❤️ ❤️
1. 归并排序的基本原理
归并排序采用分治的策略,将一个大问题分解为小问题,解决小问题,然后将它们合并以获得最终解决方案。其基本步骤如下:
- 1 . 分割( Divide ):将数组划分为两个子数组,通常是平均分割。
- 2 . 递归( Conquer ):递归地对子数组进行排序。
- 3 . 合并( Merge ):将排好序的子数组合并为一个有序的数组。
下面是一个简单的归并排序算法的 Python 实现:
def merge_sort(arr):if len(arr) > 1:mid = len(arr) // 2 # 找到数组的中间位置left_half = arr[:mid]right_half = arr[mid:]merge_sort(left_half) # 递归排序左半部分merge_sort(right_half) # 递归排序右半部分i = j = k = 0# 合并两个子数组while i < len(left_half) and j < len(right_half):if left_half[i] < right_half[j]:arr[k] = left_half[i]i += 1else:arr[k] = right_half[j]j += 1k += 1while i < len(left_half):arr[k] = left_half[i]i += 1k += 1while j < len(right_half):arr[k] = right_half[j]j += 1k += 1
归并排序的时间复杂度是 O ( n log n ),它是一种稳定的排序算法,但它需要额外的空间来存储临时数组。
2. 归并排序的优化
尽管归并排序的时间复杂度相对较低,但它在实际应用中可能会因为空间复杂度较高而受到限制。为了解决这个问题,可以进行一些优化。
2.1 自底向上的归并排序
传统的归并排序是自顶向下的,即从顶部开始递归划分子数组。在自底向上的归并排序中,我们从底部开始,首先将相邻的元素两两合并,然后是四四合并,八八合并,直到整个数组排序完成。这样可以减少递归所需的栈空间,降低空间复杂度。
以下是自底向上归并排序的 Python 实现:
def merge_sort_bottom_up(arr):n = len(arr)curr_size = 1while curr_size < n:for left in range(0, n - 1, 2 * curr_size):mid = min(left + curr_size - 1, n - 1)right = min(left + 2 * curr_size - 1, n - 1)if mid < right:merge(arr, left, mid, right)curr_size *= 2def merge(arr, left, mid, right):n1 = mid - left + 1n2 = right - midL = [0] * n1R = [0] * n2for i in range(n1):L[i] = arr[left + i]for i in range(n2):R[i] = arr[mid + i + 1]i = j = 0k = leftwhile i < n1 and j < n2:if L[i] <= R[j]:arr[k] = L[i]i += 1else:arr[k] = R[j]j += 1k += 1while i < n1:arr[k] = L[i]i += 1k += 1while j < n2:arr[k] = R[j]j += 1k += 1
2.2 最后优化
归并排序的一个缺点是它需要额外的空间来存储临时数组。为了避免这种情况,可以使用一个额外的数组来存储一半的数据,然后交替地将数据复制到原始数组中。这可以降低空间复杂度,但增加了一些额外的复制操作。
以下是这种优化方法的 Python 实现:
def merge_sort_optimized(arr):n = len(arr)temp_arr = [0] * ncurr_size = 1while curr_size < n:left = 0while left < n - 1:mid = min(left + curr_size - 1, n - 1)right = min(left + 2 * curr_size - 1, n - 1)if mid < right:merge_optimized(arr, left, mid, right, temp_arr)left += 2 * curr_sizecurr_size *= 2def merge_optimized(arr, left, mid, right, temp_arr):i = leftj = mid + 1for k in range(left, right + 1):temp_arr[k] = arr[k]k = leftwhile i <= mid and j <= right:if temp_arr[i] <= temp_arr[j]:arr[k] = temp_arr[i]i += 1else:arr[k] = temp_arr[j]j += 1k += 1while i <= mid:arr[k] = temp_arr[i]k += 1i += 1
这种优化方法减少了内存的使用,但增加了一些额外的复制操作。
3. 外部排序
归并排序还可以应用于外部排序,这是一种处理大规模数据集的排序方法。外部排序的主要思想是将大数据集分成多个小数据块,每个小数据块都可以在内存中进行排序。排序后,将这些小数据块合并成一个有序的大数据集。
下面是一个简单的外部排序示例,假设我们有一个非常大的文件,无法一次性加载到内存中进行排序。我们可以将文件划分为多个小文件块,分别进行排序,然后合并它们。
def external_sort(input_file, output_file, chunk_size):# 划分文件为多个块divide_file(input_file, chunk_size)# 对每个块进行内部排序sort_chunks()# 合并排序后的块merge_sorted_chunks(output_file)def divide_file(input_file, chunk_size):# 从输入文件中读取数据并划分为块passdef sort_chunks():# 对每个块进行内部排序passdef merge_sorted_chunks(output_file):# 合并排序后的块pass
这个示例演示了如何将大文件划分为多个小文件块,每个块都可以在内存中排序。然后,排序后的块将被合并为一个有序的输出文件。
4. 性能比较
为了演示归并排序的不同优化版本之间的性能差异,我们可以使用一些基准测试来比较它们的运行时间。下面是一个简单的性能比较示例:
import random
import timeitarr = [random.randint(1, 1000) for _ in range(1000)]# 未优化的归并排序
def merge_sort_original(arr):if len(arr) > 1:mid = len(arr) // 2left_half = arr[:mid]right_half = arr[mid:]merge_sort_original(left_half)merge_sort_original(right_half)i = j = k = 0while i < len(left_half) and j < len(right_half):if left_half[i] < right_half[j]:arr[k] = left_half[i]i += 1else:arr[k] = right_half[j]j += 1k += 1while i < len(left_half):arr[k] = left_half[i]i += 1k += 1while j < len(right_half):arr[k] = right_half[j]j += 1k += 1# 测试未优化的归并排序的性能
original_time = timeit.timeit(lambda: merge_sort_original(arr.copy()), number=1000)# 优化的归并排序
def merge_sort_optimized(arr):# 同上,省略优化后的代码# 测试优化的归并排序的性能
optimized_time = timeit.timeit(lambda: merge_sort_optimized(arr.copy()), number=1000)print("未优化的归并排序耗时:", original_time)
print("优化的归并排序耗时:", optimized_time)
在上述示例中,我们对未优化的归并排序和优化后的归并排序进行了性能测试。通过这种方式,你可以比较它们的性能并选择最适合你应用的版本。
5. 结论
归并排序是一种经典的排序算法,它使用分治策略和合并操作,具有稳定的性质和较低的时间复杂度。通过进行优化,例如自底向上的归并排序和减少内存使用的外部排序,我们可以提高归并排序的性能和适用性。根据应用的需求和资源限制,选择合适的排序算法版本,以获得最佳性能。这些优化方法可以在处理大数据集和内存受限的情况下发挥重要作用。
[ 专栏推荐 ]
😃 《Python 算法初阶:入门篇》😄
❤️【简介】:本课程是针对 Python 初学者设计的算法基础入门课程,涵盖算法概念、时间复杂度、空间复杂度等基础知识。通过实例演示线性搜索、二分搜索等算法,并介绍哈希表、深度优先搜索、广度优先搜索等搜索算法。此课程将为学员提供扎实的 Python 编程基础与算法入门,为解决实际问题打下坚实基础。

相关文章:
Python 算法高级篇:归并排序的优化与外部排序
Python 算法高级篇:归并排序的优化与外部排序 引言 1. 归并排序的基本原理2. 归并排序的优化2.1 自底向上的归并排序2.2 最后优化 3. 外部排序4. 性能比较5. 结论 引言 在计算机科学中,排序是一项基本的任务,而归并排序( Merge S…...
LeetCode--1991.找到数组的中间位置
1 题目描述 给你一个下标从 0 开始的整数数组 nums , 请你找到 最左边 的中间位置 middleIndex (也就是所有可能中间位置下标最小的一个) 中间位置 middleIndex 是满足 nums[0] nums[1] ... nums[middleIndex-1] nums[middleIndex1] nums[middleI…...
物联网数据采集网关连接设备与云平台的关键桥梁
随着工业4.0和智能制造的快速发展,物联网数据采集网关在工业物联网中的应用越来越广泛。物联网数据采集网关作为连接设备与云端之间的关键桥梁,能够实现高效、可靠、安全的数据传输和转换,为智能制造和工业4.0提供了强大的支持。 一、物联网…...
专家级数据恢复:UFS Explorer Professional Recovery Crack
UFS Explorer Professional Recovery - 一款功能强大且方便的数据恢复程序,支持检测大量文件系统、操作系统和各种类型的驱动器:从简单的闪存驱动器到复杂的复合存储(各种级别的 RAID 阵列)。 该程序由执业专家开发,并…...
2023/10/23 mysql学习
数据库修改 show databases; 展示所有数据库 create database 数据库名; 创建数据库 create database if not exists 数据库名; 如果未创建过当前数据库名则创建 drop database 数据库名; drop database if exists 数据库名;用法和创建类似 删除数据库 use 数据库名; 跳…...
软考系统架构师知识点集锦六:项目管理
一、考情分析 二、考点精讲 2.1进度管理(时间管理) 进度管理:为了确保项目按期完成所需要的管理过程。 2.1.1过程 [WBS分解的基本要求] WBS的工作包是可控和可管理的,不能过于复杂。任务分解也不能过细,一般原则WBS的树形结构不超过6层。每个工作包要…...
MacOS系统Chrome开发者模式下载在线视频
操作流程 # step1. 进入开发者模式 command option i # step2. 在搜索栏中搜索 getHttpVideoInfo.do?关键词 # step3. 在Preview的Json界面中找到video,然后选择不同resolution & duration的视频片段; # step4. 选择合适的video::chapters, 选择…...
uniapp v3+ts 使用 u-upload上传图片以及视频
上传图片方法 <u-upload :fileList"fileList1" afterRead"afterRead" delete"deletePic" name"file" multiple :maxCount"6"></u-upload> // maxCount 最大上传数const fileList1 ref([]);const file ref([…...
为什么虚拟dom会提高性能?
虚拟 DOM(Virtual DOM)是一种在前端开发中常用的技术,它可以提高性能并改善用户体验。虚拟 DOM 的原理和用处如下: 原理: 当页面状态发生变化时,虚拟 DOM 会以 JavaScript 对象的形式进行更新,而…...
2015年亚太杯APMCM数学建模大赛A题海上丝绸之路发展战略的影响求解全过程文档及程序
2015年亚太杯APMCM数学建模大赛 A题 海上丝绸之路发展战略的影响 原题再现 一带一路不是实体或机制,而是合作与发展的理念和主张。凭借现有有效的区域合作平台,依托中国与有关国家现有的双边和多边机制,利用古丝绸之路的历史象征࿰…...
js中HTMLCollection如何循环
//不带索引 let divCon document.getElementsByClassName("el-form-item__error"); if (divCon.length > 0) {for (var item of divCon) {console.log("打印:", item.innerText);} }//带有索引 let divCon document.getElementsByClassNam…...
Kafka - 3.x 副本不完全指北
文章目录 kafka 副本的基本信息Leader选举过程Kafka Controllerkafka 分区副本Leader的选举流程实际演示① 查看first的详细信息,注意观察副本分布情况② 停掉hadoop103上的kafka进程③ 再次查看first的相信信息,观察副本分布④ 处理分区leader分布不均匀…...
二分归并法将两个数组合并
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> main() {int a[5] {1,3,4,5,6};int b[4] {2,7,8,9};int c[9];int m0, n0,k0;while (m < 5 && n < 4){if (a[m] < b[n]){c[k] a[m];//谁小谁先进数组m; k;}else{c[k] b[n];k; n;}}while (m <…...
ROS自学笔记十六:URDF优化_xacro文件
xacro 是一种 XML 扩展语言,用于创建和维护 URDF(Unified Robot Description Format)文件。它允许你使用参数化、宏和条件语句等功能来更灵活、更可维护地定义机器人模型。下面是关于 xacro 的详细解释: 1. 参数化(Par…...
XMLHttpRequest拦截请求和响应
环境: angular 实现: 拦截请求 向请求信息增加字段 拦截响应 过滤返回值 响应拦截: 根据angular使用的XMLHttpRequest 将对原本的请求转移到另一个将监听返回事件挂载到另一个世纪发送请求的xml上 使用get set 将客户端获取的res…...
前端 读取/导入 Excel文档
情况: 需要通过Excel表,将数据导入到数据库,但是后台人员出差了,我又只会PHP,没用过node,所以只能前端导入Excel文件,然后循环调用后台的单条添加接口了。 库: Excel.js(…...
聊聊springboot的TomcatMetricsBinder
序 本文主要研究一下springboot的TomcatMetricsBinder TomcatMetricsAutoConfiguration org/springframework/boot/actuate/autoconfigure/metrics/web/tomcat/TomcatMetricsAutoConfiguration.java Configuration(proxyBeanMethods false) ConditionalOnWebApplication C…...
《动手学深度学习 Pytorch版》 10.6 自注意力和位置编码
在注意力机制中,每个查询都会关注所有的键-值对并生成一个注意力输出。由于查询、键和值来自同一组输入,因此被称为 自注意力(self-attention),也被称为内部注意力(intra-attention)…...
2023年第四届MathorCup高校数学建模挑战赛——大数据竞赛B题 实现代码
根据之前发布的思路 第一步 进行数据合并 import pandas as pd# 读取所有附件的数据 data1 pd.read_excel(附件一.xlsx) data2 pd.read_excel(附件二.xlsx) data3 pd.read_excel(附件三.xlsx) data4 pd.read_excel(附件四.xlsx)# 根据商品编码将附件一和附件二连接 combi…...
larvel 中的api.php_Laravel 开发 API
Laravel10中提示了Target *classController does not exist,为什么呢? 原因是:laravel8开始写法变了。换成了新的写法了 解决方法一: 在路由数组加入App\Http\Controllers\即可。 <?phpuse Illuminate\Support\Facades\Route;…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...
sqlserver 根据指定字符 解析拼接字符串
DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...
【JavaSE】绘图与事件入门学习笔记
-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...
基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解
JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用,结合SQLite数据库实现联系人管理功能,并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能,同时可以最小化到系统…...
【Go语言基础【13】】函数、闭包、方法
文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数(函数作为参数、返回值) 三、匿名函数与闭包1. 匿名函数(Lambda函…...
第7篇:中间件全链路监控与 SQL 性能分析实践
7.1 章节导读 在构建数据库中间件的过程中,可观测性 和 性能分析 是保障系统稳定性与可维护性的核心能力。 特别是在复杂分布式场景中,必须做到: 🔍 追踪每一条 SQL 的生命周期(从入口到数据库执行)&#…...
9-Oracle 23 ai Vector Search 特性 知识准备
很多小伙伴是不是参加了 免费认证课程(限时至2025/5/15) Oracle AI Vector Search 1Z0-184-25考试,都顺利拿到certified了没。 各行各业的AI 大模型的到来,传统的数据库中的SQL还能不能打,结构化和非结构的话数据如何和…...
Linux基础开发工具——vim工具
文章目录 vim工具什么是vimvim的多模式和使用vim的基础模式vim的三种基础模式三种模式的初步了解 常用模式的详细讲解插入模式命令模式模式转化光标的移动文本的编辑 底行模式替换模式视图模式总结 使用vim的小技巧vim的配置(了解) vim工具 本文章仍然是继续讲解Linux系统下的…...
视觉slam--框架
视觉里程计的框架 传感器 VO--front end VO的缺点 后端--back end 后端对什么数据进行优化 利用什么数据进行优化的 后端是怎么进行优化的 回环检测 建图 建图是指构建地图的过程。 构建的地图是点云地图还是什么信息的地图? 建图并没有一个固定的形式和算法…...
