算法思想:
归并排序使用的分治法策略,基本思想是:先将一个无序的序列分成有数个无序的小序列,直到序列中只有一个数,然后开始合并序列,这时合并的序列就是有序的序列,直到合并成最后一个就完成排序,这就是归并排序。
归并排序流程:
- 选择序列中间位置开始将序列分为两份,这两个序列继续进行归并排序。
- 当序列中只有一个数时,不再拆分(因为此时一个数序列就是有序的),然后开始合并序列,两个有序序列很容易合并成一个有序序列,
时间复杂度:
算法实现:
C++
void merge_sort(int a[],int l,int r)
{
if(l>=r) return; //当序列中只有一个数时结束递归
int mid=(l+r)>>1;
merge_sort(a,l,mid);merge_sort(a,mid+1,r);//将序列一分为二继续归并排序
int k=0,i=l,j=mid+1;
while(i<=mid&&j<=r) //将两个有序的序列合并成一个有序的序列
{
if(a[i]>a[j]) tmp[k++]=a[j++];
else tmp[k++]=a[i++];
}
while(i<=mid) tmp[k++]=a[i++];//插入左边序列中最后没有参与比较的数
while(j<=r) tmp[k++]=a[j++];//插入右边序列中最后没有参与比较的数
for(i=l,k=0;i<=r;i++,k++) a[i]=tmp[k];
}
归并排序的应用
归并排序最常见的一个应用就是查找序列中逆序对的个数。
代码
int cnt=0;
void merge_sort(int a[],int l,int r)
{
if(l>=r) return; //当序列中只有一个数时结束递归
int mid=(l+r)>>1;
merge_sort(a,l,mid);merge_sort(a,mid+1,r);//将序列一分为二继续归并排序
int k=0,i=l,j=mid+1;
while(i<=mid&&j<=r) //将两个有序的序列合并成一个有序的序列
{
//当左边的序列数字比右边的大,说明构成逆序对,
//并且左边最后的数字 都与当前右边的数字构成逆序对
if(a[i]>a[j]) {tmp[k++]=a[j++];cnt+=(mid-i+1)}
else tmp[k++]=a[i++];
}
while(i<=mid) tmp[k++]=a[i++];//插入左边序列中最后没有参与比较的数
while(j<=r) tmp[k++]=a[j++];//插入右边序列中最后没有参与比较的数
for(i=l,k=0;i<=r;i++,k++) a[i]=tmp[k];
}