归并排序

算法描述

递归排序是把长度为n的输入序列分成两个长度为n/2的子序列,分别对这两个子序列采用递归排序,将两个排序好的子序列合并成一个最终的排序序列。它包含了分治的思想。

代码演示

public static void mergeSort(int arr[],int left,int right)
{
	if(left<right)
	{ 
		int mid=(left+right)/2;
		mergeSort(arr,left,mid);
		mergeSort(arr,mid+1,right);
		merge(arr,left,mid,right);
	}
}

public static void merge(int[] arr,int l,int m,int r)
{	
	//计算合并的两个子数组的大小
	int n1=m-l+1;
	int n2=r-m;
	//创建两个临时的子数组,存储要合并的两个子数组
	int L[]=new int[n1];
	int R[]=new int[n2];
	
	//拷贝数据
	for(int i=0;i<n1;++i)
		L[i]=arr[l+i];
	for(int j=0;j<n2;++j)
		R[j]=arr[m+1+j];

	//初始化两个临时子数组的下标
	int i=0,j=0;
	//初始化合并后数组的子下标(left)
	int k=l;
	while(i<n1 && j<n2)
	{
		if(L[i]<=R[j])
		{
			arr[k]=L[i];
			i++;
		}
		else
		{
			arr[k]=R[j];
			j++;
		}
		k++;
	}
	//如果L[]有剩余,拷贝
	while(i<n1)
	{
		arr[k]=L[i];
		i++;
		k++;
	}
	//如果R[]中有剩余,拷贝
	while(j<n2)
	{
		arr[k]=R[j];
		j++;
		k++;
	}
}
	

复杂度分析

时间复杂度

归并排序总时间=拆分时间+子数组排好序时间+合并时间
无论每个数组有多少个数都是折半拆分,也就是代码中的int m=(l+r)/2;,所以拆分时间就是个常数o(1),可以忽略不计。
则:归并排序时间=子数组排序时间+合并时间

归并排序的时间复杂度为:

  • 最好情况:T(n) = O(n)
  • 最差情况:T(n) = O(nlogn)
  • 平均情况:T(n) = O(nlogn)

空间复杂度

在合并的时候,我们使用了存储待合并的两个数组元素的空间,这个数组大小依次开辟的就是1,2,3,4,8,…, n/2, 但是开辟了两个,所以可能开辟的空间大小为2,4,8,…,n,归并排序的空间复杂度为o(n)。

稳定性分析

归并排序是稳定的排序算法,归并排序稳定的根本原因在于合并的时候对值相同的两个关键字不存在交换的可能性。

©️2020 CSDN 皮肤主题: 1024 设计师:上身试试 返回首页