归并排序

622 阅读1分钟

算法思想:

归并排序使用的分治法策略,基本思想是:先将一个无序的序列分成有数个无序的小序列,直到序列中只有一个数,然后开始合并序列,这时合并的序列就是有序的序列,直到合并成最后一个就完成排序,这就是归并排序。

归并排序流程:

  1. 选择序列中间位置开始将序列分为两份,这两个序列继续进行归并排序。
  2. 当序列中只有一个数时,不再拆分(因为此时一个数序列就是有序的),然后开始合并序列,两个有序序列很容易合并成一个有序序列,

时间复杂度:

O(nlog2(n))O(nlog2(n))

算法实现:

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];
 }