排序 —— 归并排序

一、算法思想

归并排序可以看作一个分而治之的过程:先将整个序列分为两半,对每一半分别进行归并排序,将得到两个有序序列,然后将这两个序列归并成一个序列即可


二、算法过程

在这里插入图片描述


三、实现

//	SR和TR1、TR2是等长的,由于是对不同的区间进行修改,故各子过程不会相互影响
//	SR不会发生改变
//	TR2存储的是中间过程
//	TR1的结果会返回到上一层的TR2,作为上一层的中间结果
void mergeSort(int SR[],int TR1[],int low,int high)
//	将无序的SR[low...high]归并排序为有序的TR1[low...high]
{
	if(low==high)	TR1[low]=SR1[low];
	else
	{
		int mid=(low+high)/2;
		mergeSort(SR,TR2,low,mid);	//	归并排序前半段,将无序的SR[low...mid]归并排序为有序的TR2[low...mid]
		mergeSort(SR,TR2,mid+1,high);	//	归并排序后半段,将无序的SR[mid+1...high]归并排序为有序的TR2[mid+1...high]
		merge(TR2,TR1,low,mid,high);	//	将TR2[low...mid]和TR2[mid+1...high]归并到TR1[low...high]

	}
}

void merge(int TR2[],int TR1[],int low,int mid,int high)
//	将有序TR2[low...mid]和TR2[mid+1...high]归并到TR1[low...high]
{
	int i=low;	//	i指示TR2[low...mid]的首位,j指示TR2[mid+1...high]的首位,
				//	k指示TR1[low...high]的首位
	int j=mid+1;
	for(k=i;i<=mid&&j<=high;k++)
	{
		if(TR2[i]<=TR2[j])
		{
			TR1[k]=TR2[i];
			i++;
		}
		else
		{
			TR1[k]=TR2[j];
			j++;
		}
	}
	while(i<=mid)
	{
		TR1[k]=TR2[i];
		i++;
		k++;
	}
	while(j<=high)
	{
		TR1[k]=TR2[j];
		j++;
		k++;
	}
}

四、算法性能分析

(1)时间复杂度分析

由算法程序可得 T(n)=T(n/2)+n,其中,n是指当前的 归并操作 的执行次数(即:要归并的两个子序列中关键字个数之和),故时间复杂度为 O(nlog n)

可见归并排序时间复杂度和初始序列无关,即平均时间复杂度、最好时间复杂度、最坏时间复杂度均为 O(nlog n)

(2)空间复杂度分析

因为归并排序需要转存整个待排序列,需要用到TR1[ ]和TR2[ ],故其空间复杂度为O(n)

(3)稳定性

归并排序是把序列递归地分成短序列,递归出口是短序列只有1个元素(认为直接有序)或者2个序列(1次比较和交换),然后把各个有序的段序列合并成一个有序的长序列,不断合并直到原序列全部排好序。可以发现,在1个或2个元素时,1个元素不会交换,2个元素如果大小相等也没有人故意交换,这不会破坏稳定性。那么,在短的有序序列合并的过程中,稳定是是否受到破坏?没有,合并过程中我们可以保证如果两个当前元素相等时,我们把处在前面的序列的元素保存在结果序列的前面,这样就保证了稳定性。所以,归并排序也是稳定的排序算法。

猜你喜欢

转载自blog.csdn.net/starter_____/article/details/94315911