归并排序详解

归并排序

排序的概念

排序是将一批(组)任意次序的记录重新排列成按关键字有序的记录序列的过程。

注意:首先需要打破僵化思维,排序的关键字可以指定多个,’有序‘的概念也是可以指定的,不只有递增或递减,排序的元素也不只有数字,任何可区分的元素都可以进行排序,因此排序算法会频繁的出现在各类算法中,不同的排序算法带来的思想常常是解决不同问题的突破点。

关键概念

归并:是指将两个或两个以上的有序序列合并成一个有序序列。

这里考虑一下一次归并的时间复杂度:
	朴素考虑:如果我们将两个有序序列拼接在一起,然后得到的新序列进行一次排序,根据不同的排序算法时间复杂度可能是O(nlogn)~O(n^2)
	当然这不可能是实现归并排序的基础,我们要提高效率就需要充分利用两个序列有序的条件。
	
	高效考虑:在两个序列中找到一个最小的时间复杂度度是O(1),因为这个最小不是a序列的最小就是b序列的最小

在这里插入图片描述

继续思考:我们一直进行以上操作,就可以用O(n)的时间复杂度进行一次归并,归并算法就是以这个高效的操作为基础的。

算法思路

我们了解了归并,如何利用归并排序呢?
很自然我们想到了,对许多有序序列进行归并,就可以得到一个有序的总序列。但最初的有序是什么呢?
我们可以认为所有的排序元素就是“有序的”,因为一个元素没有逆序对。

那有很多不同的归并策略,哪种最高效呢?
我们首先考虑一个极端情况,我们有n个元素,那么就有了n个长度1的有序序列,一个一个的归并将所有的序列连接起来,那么就需要对n个元素进行n次取最小,时间复杂度是O(n2)。
在这里插入图片描述
归并的效率是O(n),那么总复杂度就取决于归并的次数,如何使效率最小呢?二分
在这里插入图片描述

这样只用进行logn次归并,由此得到了算法思路。

代码实现

递归实现,非递归也能实现,可以自己试试

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
void merge(int a[],int l,int r,int mid)//一次归并,通过左右中三个点划分数组
{
  int aux[r-l+1],i,j,k;
  for(k=l;k<=r;k++)
  	aux[k-l]=a[k];//记录原来的序列,因为新序列会覆盖掉a
  i=l;//i指向第一个序列的第一项
  j=mid+1;//j指向第二个序列的第一项
  for(k=l;k<=r;k++){
  	if(i>mid){//第一个序列没了,只能是第二个序列最小
  		a[k]=aux[j-l];
  		j++;
	}
	else if(j>r){//第二个序列没了
		a[k]=aux[i-l];
		i++;
	}
	else if(aux[i-l]>aux[j-l]){//第一个序列头比第二个序列头小
		a[k]=aux[j-l];
		j++;
	}
	else{//反之
		a[k]=aux[i-l];
		i++;
	}
  }	
}
 
void merge_sort(int a[],int l,int r){//函数最终效果是通过归并排序使l到r这段序列有序
    if(l>=r)
		return ;//元素本身有序
	int mid=(l+r)/2;
	//在进行归并前需要两端序列有序,所以需要先对两段序列排序
	merge_sort(a,l,mid);
	merge_sort(a,mid+1,r);
	merge(a,l,r,mid);	//归并
}
 
int main(){
	int a[105],n,i;
	scanf("%d",&n);//序列元素个数
	for(i=0;i<n;i++)
	scanf("%d",&a[i]);//序列
	
	merge_sort(a,0,n-1);//开始归并
	
	for(i=0;i<n;i++)
	printf("%d ",a[i]);
	return 0;
 }
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值