归并排序是一种效率较高的排序算法,总体时间复杂度为O(logn)
它主要分成归和并两部分操作来进行:
归:将当前数组分成两部分
并:将两部分排好序的区间合并成一个排好序的较大的空间
我们通过下面一组例子来进行演示:比如我们要对[5,1,9,8,3,6,4,7]进行排序
将数组分成两部分:
5 1 9 8 3 6 4 7
l r
l1 r1 l2 r2
将数组递归地分成两部分:
5 1 9 8 3 6 4 7
l r
l1 r1 l2 r2
递归地对第一个子区间进行排序,再将这两个区间分成两个子区间
5 1 9 8 3 6 4 7
l r
L1/R1
L2/R2
这时,两个子区间长度都为1,排序完成,此时再将两个有序子区间合并成一个较大的子区间
1 5 9 8 3 6 4 7
l r
类似地,将9,8这两个子区间也进行排序
5 1 8 9 3 6 4 7
l r
两个子区间完成排序后,对其进行合并操作
1 5 8 9 3 4 6 7
L1 R1 L2 R2
然后通过递归函数对右半部分也进行相应的操作,最后得到有序数组
实现代码如下:
void merge_sort(vector<int> &nums, int left, int right) {
if (left == right) {
return;
}
//将数组进行分割操作
int mid = (left + right) / 2;
merge_sort(nums, left, mid);
merge_sort(nums, mid + 1, right);
int l = left;
int r = mid + 1;
int loc = left;
int temps[50010] = { 0 };
//两个子序列进行大小比较
while (l <= mid && r <= right) {
if (nums[l] < nums[r]) {
temps[loc++] = nums[l++];
}
else {
temps[loc++] = nums[r++];
}
}
//补充剩下的元素
while (l <= mid) {
temps[loc++] = nums[l++];
}
while (r <= right) {
temps[loc++] = nums[r++];
}
for (int i = left; i <= right; ++i) {
nums[i] = temps[i];
}
}