归并排序
归并排序(Merge Sort)是一种基于分治思想的高效排序算法。它将一个大的数组逐步分解为多个小数组,然后将这些小数组排序后再合并起来,最终得到一个有序的大数组。以下为你详细介绍:
1. 基本原理
- 分解:将待排序的数组不断地分成两个大致相等的子数组,直到每个子数组只包含一个元素(单个元素的数组天然有序)。这个过程可以通过递归实现。
- 合并:将两个或多个已排序的子数组合并成一个更大的有序数组。合并时,通过比较两个子数组的元素,依次将较小的元素放入结果数组中,直到所有元素都被合并。
2. 算法步骤
- 分解步骤:
- 找到数组的中间位置
mid
,通常通过(left + right) // 2
计算得到,其中left
是数组的起始索引,right
是数组的结束索引。 - 对左半部分数组
arr[left:mid + 1]
递归调用归并排序。 - 对右半部分数组
arr[mid + 1:right + 1]
递归调用归并排序。
- 找到数组的中间位置
- 合并步骤:
- 创建两个临时数组
left_half
和right_half
,分别存储左右两个子数组的内容。 - 使用两个指针
i
和j
分别指向left_half
和right_half
的起始位置,再使用一个指针k
指向要合并的目标数组arr
的起始位置。 - 比较
left_half[i]
和right_half[j]
的大小,将较小的元素放入arr[k]
中,并将相应的指针后移一位。 - 如果其中一个子数组的元素全部放入
arr
中,将另一个子数组剩余的元素直接复制到arr
中。
- 创建两个临时数组
示例
使用归并排序[7, 1, 4, 8, 5, 2]:
3. 代码实现
以下是 Python 语言实现归并排序的代码:
def merge_sort(arr):
if len(arr) <= 1:
return arr
mid = len(arr) // 2
left_half = arr[:mid]
right_half = arr[mid:]
left_half = merge_sort(left_half)
right_half = merge_sort(right_half)
return merge(left_half, right_half)
def merge(left, right):
result = []
i = j = 0
while i < len(left) and j < len(right):
if left[i] < right[j]:
result.append(left[i])
i += 1
else:
result.append(right[j])
j += 1
result.extend(left[i:])
result.extend(right[j:])
return result
4. 算法分析
- 时间复杂度:
- 归并排序的分解过程会将数组不断二分,直到每个子数组只有一个元素,这个过程的深度为
。 - 每层分解的合并操作,都需要对数组中的所有元素进行处理,操作次数为
n
。 - 因此,归并排序的时间复杂度在最好、最坏和平均情况下均为
,其中n
是数组的长度。
- 归并排序的分解过程会将数组不断二分,直到每个子数组只有一个元素,这个过程的深度为
- 空间复杂度:
- 归并排序在合并过程中需要创建临时数组来存储左右子数组的内容,这需要额外的空间。
- 空间复杂度主要取决于临时数组的大小,在最坏情况下,临时数组的大小与原数组相同,所以空间复杂度为
。
- 稳定性:归并排序是稳定的排序算法。在合并过程中,当左右子数组中出现相等元素时,先将左边子数组中的元素放入结果数组,这样就保证了相等元素的相对顺序不变。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?