归并排序
基本思想:
将两个或两个以上的有序子序列“归并”为一个有序序列。
通常使用2-路归并排序
,即将两个位置相邻的有序子序列R[l…m]和R[m…n]归并为一个有序序列R[l…n]
示例
对于序列48 34 60 80 75 12 26 48
,进行归并排序
整个归并排序需要进行 l o g 2 n log_2n log2n趟
关键问题:将两个有序序列合并成一个有序序列:
- 创建空白Lc
- 依次从La和Lb中取元素值较小的结点插入Lc的最后,直到一个表变空
- 继续将另一个表的剩余结点插入Lc表的最后
代码
- 合并两个有序子表
void Merge(int arr[], int low, int mid, int high) {
int i = low; // 第一个子表的起始位置
int j = mid + 1; // 第二个子表的起始位置
int k = 0; // 临时数组的索引
int* temp = (int*)malloc((high - low + 1) * sizeof(int)); // 临时数组
// 合并两个有序子表
while (i <= mid && j <= high) {
if (arr[i] <= arr[j]) {
temp[k++] = arr[i++]; // 将较小的元素放入临时数组
}
else {
temp[k++] = arr[j++];
}
}
// 将剩余的元素复制到临时数组
while (i <= mid) {
temp[k++] = arr[i++];
}
while (j <= high) {
temp[k++] = arr[j++];
}
// 将临时数组的内容复制回原数组
for (i = low, k = 0; i <= high; i++, k++) {
arr[i] = temp[k];
}
free(temp); // 释放临时数组
}
- 递归实现归并排序
void MergeSort(int arr[], int low, int high) {
if (low < high) {
int mid = (low + high) / 2; // 计算中间位置
MergeSort(arr, low, mid); // 对左半部分排序
MergeSort(arr, mid + 1, high); // 对右半部分排序
Merge(arr, low, mid, high); // 合并两个有序子表
}
}
- 主函数
int main() {
int arr[] = { 48, 34, 60, 80, 75, 12, 26, 48 }; // 待排序数组
int n = sizeof(arr) / sizeof(arr[0]); // 数组长度
// 调用归并排序
MergeSort(arr, 0, n - 1);
return 0;
}
时间复杂度
O(nlog2n)
空间复杂度
O(n)
稳定性
归并算法是一种稳定算法