归并排序(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
中。
- 创建两个临时数组
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. 算法分析
- 时间复杂度:
- 归并排序的分解过程会将数组不断二分,直到每个子数组只有一个元素,这个过程的深度为 \(logn\)。
- 每层分解的合并操作,都需要对数组中的所有元素进行处理,操作次数为
n
。 - 因此,归并排序的时间复杂度在最好、最坏和平均情况下均为 \(O(nlogn)\),其中
n
是数组的长度。
- 空间复杂度:
- 归并排序在合并过程中需要创建临时数组来存储左右子数组的内容,这需要额外的空间。
- 空间复杂度主要取决于临时数组的大小,在最坏情况下,临时数组的大小与原数组相同,所以空间复杂度为 \(O(n)\)。
- 稳定性:归并排序是稳定的排序算法。在合并过程中,当左右子数组中出现相等元素时,先将左边子数组中的元素放入结果数组,这样就保证了相等元素的相对顺序不变。