在我平时的练习与刷题当中我基本不用归并排序,快速排序这类排序,直接就是一个sort排序,简单了事。但是今天的训练赛当中遇到了一道题,它使用了归并排序的分治思想。正好有些遗忘,今天来复习一下。
定义:归并排序(Merge sort)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。
所谓归并操作就是将两个有序的序列通过操作变成一个有序的数列。这种方法十分高效,时间复杂度为O(M+N)M+N为两个子数组的元素和。
下面是一张图,举例怎么将一个数组分开
下面是代码表示怎么用递归将数组分开
void merge_sort(int l,int r)
{
if (l>=r) return ;
int mid = (l+r)>>1;
merge_sort(l,mid);
merge_sort(mid+1,r);
}
这下面一部分是将两个有序的子数组合并成一个大的有序数组
void merge_sort(int l, int r)
{
if (l >= r)
return;
int mid = l + r >> 1;//取中间值
merge_sort(l, mid);//有序的数组从q[l]到q[mid]
merge_sort(mid + 1, r);//有序的数组从q[mid+1]到q[r]
int k = 0;//新数组tmp的下标
int i = l;//初始值
int j = mid + 1;//初始值
while (i <= mid && j <= r)//当指针i,j均未到达该数组的有边界时
{
if (q[i] <= q[j]) //如果q[i]小于q[j],则将q[i]输入到tmp[k],然后i++,指针i向右移一位
tmp[k++] = q[i++];
else //如果q[i]大于q[j],则将q[j]输入到tmp[k],然后j++,指针j向右移一位
tmp[k++] = q[j++];
}
//在指针i或者指针j走到尽头,则将另一指针后面的数直接加到tmp[k]的末尾即可
while (i <= mid) //当指针j走到尽头,而指针i未走到尽头时
tmp[k++] = q[i++];
while (j <= r) //当指针i走到尽头,而指针j未走到尽头时
tmp[k++] = q[j++];
for (i = l, j = 0; i <= r; i++, j++) //将tmp[]赋值给q[]
q[i] = tmp[j];
}
完整代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
int n;
int q[N], tmp[N];//tmp[N]是辅助储存结果的数组
void merge_sort(int q[], int l, int r)
{
if (l >= r)
return;
int mid = l + r >> 1;//取中间值
merge_sort(q, l, mid);//有序的数组从q[l]到q[mid]
merge_sort(q, mid + 1, r);//有序的数组从q[mid+1]到q[r]
int k = 0;//新数组tmp的下标
int i = l;//初始值
int j = mid + 1;//初始值
while (i <= mid && j <= r)//当指针i,j均未到达该数组的有边界时
{
if (q[i] <= q[j]) //如果q[i]小于q[j],则将q[i]输入到tmp[k],然后i++,指针i向右移一位
tmp[k++] = q[i++];
else //如果q[i]大于q[j],则将q[j]输入到tmp[k],然后j++,指针j向右移一位
tmp[k++] = q[j++];
}
//在指针i或者指针j走到尽头,则将另一指针后面的数直接加到tmp[k]的末尾即可
while (i <= mid) //当指针j走到尽头,而指针i未走到尽头时
tmp[k++] = q[i++];
while (j <= r) //当指针i走到尽头,而指针j未走到尽头时
tmp[k++] = q[j++];
for (i = l, j = 0; i <= r; i++, j++) //将tmp[]赋值给q[]
q[i] = tmp[j];
}
int main()
{
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
cin >> n;
for (int i = 0; i < n; i++)
cin >> q[i];
merge_sort(q, 0, n - 1);
for (int i = 0; i < n; i++)
printf("%d ", q[i]);
return 0;
}