归并排序

归并排序是完全遵循 分治法实现的。 分解:分解待排序的n个元素的序列成各具n/2个元素的两个子序列。 解决:使用归并排序 递归地排序两个子序列。 合并:合并两个已排序的子序列以产生已排序的序列。归并排序的 关键操作是“合并”步骤中两个已排序序列的合并。
 
下图展示归并排序的全部过程,以数组{38,27,43,3,9,82,10}为例。
 
 
两个有序序列的合并,只要比较两个序列中的第一个数,谁小取谁。
/*把数组arr[l..m]和 arr[m+1...r]合并*/ 
void merge(int arr[],int l,int m,int r){
	int i,j,k;
	int n1 = m-l+1;
	int n2 = r-m;
	int L[n1], R[n2];
	/*复制arr[]中的数据 */
 	for(i=0;i<n1;i++)  
		L[i] = arr[i+l] ;
		
 	for(j=0;j<=n2;j++)
	 	R[j] = arr[j+m+1];
	 	
 	i=0;k=l;j=0;
 	/*合并*/ 
 	while(i<n1&&j<n2){
 		if(L[i]<=R[j])	
		 	arr[k++] = L[i++];
 		else 
			arr[k++]=R[j++];
	 }
	 while(i<n1) 
	 	arr[k++] = L[i++];
	 	
	 while(j<n2) 
	 	arr[k++] = R[j++];
}

   具体思路:先将数组分成1,2两组,如果2组中的数据已经是有序的,则将这两个数组合并。但是如何实现有序呢?可以继续将1,2两组各自再分成两组。当只有一个数据时就是有序的,在合并相邻的两组数据即可。简单的说就是: 先递归分解, 再合并。
 
#include<iostream>
#include<cstdio>
using namespace std;
/*把数组arr[l..m]和 arr[m+1...r]合并*/ 
void merge(int arr[],int l,int m,int r){
	int i,j,k;
	int n1 = m-l+1;
	int n2 = r-m;
	int L[n1], R[n2];
	/*复制arr[]中的数据 */
 	for(i=0;i<n1;i++)  
		L[i] = arr[i+l] ;
		
 	for(j=0;j<=n2;j++)
	 	R[j] = arr[j+m+1];
	 	
 	i=0;k=l;j=0;
 	/*合并*/ 
 	while(i<n1&&j<n2){
 		if(L[i]<=R[j])	
		 	arr[k++] = L[i++];
 		else 
			arr[k++]=R[j++];
	 }
	 while(i<n1) 
	 	arr[k++] = L[i++];
	 	
	 while(j<n2) 
	 	arr[k++] = R[j++];
}
/*递归分解*/ 
void mergeSort(int arr[],int l,int r){
	if(l<r){
		int m=l+(r-l)/2;
		mergeSort(arr,l,m);
		mergeSort(arr,m+1,r);
		merge(arr,l,m,r);
	}
}

int main(){
	int arr[]={38,27,43,3,9,82,10};
	int arr_size=sizeof(arr)/sizeof(arr[0]);
	mergeSort(arr,0,arr_size-1);
	for(int i=0;i<arr_size;i++){
		printf("%d%c",arr[i],(i==arr_size-1)?'\n':' ');
	}
	return 0;
}
 
递归排序是一个效率很高的排序方法。时间复杂度为:O(N*logN)。空间复杂度:O(n)。稳定排序。
 
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值