归并排序原理和步骤
1. 将数组分成两半,直到每个子数组的长度为1
首先,将数组分成两半。如果数组的长度大于1,将其从中间分割为两个子数组。对每个子数组继续进行这个过程,直到每个子数组的长度为1。此时,所有子数组都是有序的,因为单个元素的数组天然是有序的。
2. 递归地对每个子数组进行排序
在将数组分割为单个元素之后,通过递归方法对每个子数组进行排序。归并排序的递归性质允许我们在底层子数组有序后逐层向上合并已排序的子数组。
3. 合并两个已排序的子数组,得到一个已排序的数组
合并步骤是归并排序的核心。对于两个已经排序的子数组,通过比较它们的元素,将较小的元素依次放入新的数组中,直到所有元素都被处理完。这个过程会生成一个新的已排序数组。
4. 重复以上步骤,直到所有子数组合并成一个最终的排序数组
重复进行分割和合并的步骤,最终将所有子数组合并成一个整体,并且这个整体是有序的。通过这种递归分割和合并的方式,归并排序能够在 O(n log n) 的时间复杂度内完成对数组的排序。
归并排序的完整步骤
- 分割: 将数组分成两个子数组。
- 递归排序: 递归地对每个子数组进行归并排序。
- 合并: 合并两个已排序的子数组,生成一个新的已排序数组。
- 重复: 继续对每个子数组进行分割、排序和合并,直到所有子数组合并成一个整体。
归并排序的伪代码如下:
void mergeSort(vector<int>& arr, int left, int right) {if (left < right) {int mid = left + (right - left) / 2;// 递归排序左半部分mergeSort(arr, left, mid);// 递归排序右半部分mergeSort(arr, mid + 1, right);// 合并已排序的子数组merge(arr, left, mid, right);}
}void merge(vector<int>& arr, int left, int mid, int right) {int n1 = mid - left + 1;int n2 = right - mid;vector<int> leftArr(n1), rightArr(n2);for (int i = 0; i < n1; ++i)leftArr[i] = arr[left + i];for (int j = 0; j < n2; ++j)rightArr[j] = arr[mid + 1 + j];int i = 0, j = 0, k = left;while (i < n1 && j < n2) {if (leftArr[i] <= rightArr[j]) {arr[k] = leftArr[i];++i;} else {arr[k] = rightArr[j];++j;}++k;}while (i < n1) {arr[k] = leftArr[i];++i;++k;}while (j < n2) {arr[k] = rightArr[j];++j;++k;}
}
Python实现如下:
def merge_sort(arr):"""对数组进行归并排序:param arr: 待排序的数组:return: 已排序的数组"""# 如果数组的长度为0或1,直接返回数组if len(arr) <= 1:return arr# 找到数组的中间点mid = len(arr) // 2# 递归地对左右两个子数组进行排序left = merge_sort(arr[:mid])right = merge_sort(arr[mid:])# 合并两个已排序的子数组return merge(left, right)def merge(left, right):"""合并两个已排序的子数组:param left: 左子数组:param right: 右子数组:return: 合并后的已排序数组"""result = []i = j = 0# 合并两个子数组while i < len(left) and j < len(right):if left[i] < right[j]:result.append(left[i])i += 1else:result.append(right[j])j += 1# 追加剩余的元素result.extend(left[i:])result.extend(right[j:])return result