归并排序算法详解---C语言实现

其他排序

基数排序
堆排序
插入排序和希尔排序
快速排序
冒泡排序和选择排序

归并排序

前备知识:如果数组中只有一个数,那么这个数组一定是有序的!

核心思想:将两个有序的数组合并为一个有序的数组(运用了分组的思想:递归)
实现过程:对于如下数组进行归并排序,过程如下:
在这里插入图片描述如上所示,由于归并排序是将两个有序的数组合并为一个有序的数组,因此我们首先是对上述数组进行拆分,数组长度为nLen = 9,因此将数组均分为nLen/2 = 4,拆分后如下图所示:
归并排序算法详解---C语言实现_第1张图片

如上图所示,经过一次折半将数组拆分为了两个数组,由于归并排序的思想是将两个有序的数组进行合并,因此我们需要继续对数组进行拆分,拆分后如下图所示:

归并排序算法详解---C语言实现_第2张图片如上图所示,数组基于上次两个数组拆分为了4个数组,下面四个数组中有的有两个元素,有的有三个元素,而且有些数组我们看起来他们已经是有序的,但是计算机并不知道他们是否有序,只有遍历一遍才会知道,但是遍历数组显然不是我们排序的目的,因此我们需要进一步拆分,最终将数组拆分后的图如下:
归并排序算法详解---C语言实现_第3张图片我们知道,当数组只有一个元素时,一定是有序的,而归并排序就是将两个有序的数组合并成一个有序的数组。因此,我们将拆分后的数组进行合并,如下图所示:
归并排序算法详解---C语言实现_第4张图片如上所示,我们将最后一层的数进行了合并,之后再对上一层合并,依次进行,如下图所示:
归并排序算法详解---C语言实现_第5张图片继续回溯上一层合并
归并排序算法详解---C语言实现_第6张图片继续回溯上一层合并…
归并排序算法详解---C语言实现_第7张图片如上图所示,当返回第一层的时候,数组已经排好序。我们从归并的过程可以看出,归并的过程就是一个递归的过程,先递归将数组拆分,拆分到最小后将数组合并,合并后回溯。

代码实现

#include 
#include 

void Print(int arr[],int nLen)
{
	if(arr == NULL || nLen <= 0) return;

	for(int i = 0;i < nLen;i++)
	{
		printf("%d\t",arr[i]);
	}
	printf("\n");
}
void Merge(int arr[],int nBegin1,int nEnd1,int nBegin2,int nEnd2)
{
	if(arr == NULL || nBegin1 > nEnd1 || nBegin2 > nEnd2)
		return;
	int nLen = nEnd2 - nBegin1 + 1;
	int *parr = (int *)malloc(sizeof(int)*nLen);
	int nIndex = nBegin1;
	int i = 0;
	//合并
	while(nBegin1 <= nEnd1 && nBegin2 <= nEnd2)
	{
		if(arr[nBegin1] <= arr[nBegin2])
		{
			parr[i++] = arr[nBegin1++];
		}
		else
		{
			parr[i++] = arr[nBegin2++];
		}
	}
	while(nBegin1 <= nEnd1)
	{
		parr[i++] = arr[nBegin1++];
	}
	while(nBegin2 <= nEnd2)
	{
		parr[i++] = arr[nBegin2++];
	}
	for(i = 0;i < nLen;i++)
	{
		arr[nIndex++] = parr[i];
	}
	free(parr);
	parr = NULL;
}
void MergeSort(int arr[],int nBegin,int nEnd)
{
	if(arr == NULL || nBegin >= nEnd)
		return ;

	int nMid = nBegin + (nEnd - nBegin)/2;//折半

	//左
	MergeSort(arr,nBegin,nMid);
	//右
	MergeSort(arr,nMid+1,nEnd);
	//合并
	Merge(arr,nBegin,nMid,nMid+1,nEnd);
}

int main()
{
	int arr[] = {3,67,287,9,3,9,23,56,7};
	MergeSort(arr,0,sizeof(arr)/sizeof(arr[0])-1);
	Print(arr,sizeof(arr)/sizeof(*arr));
	return 0 ;	
}

最好时间复杂度:O(nlogn)

最坏时间复杂度:O(nlogn)

平均时间复杂度:O( nlogn)

空间复杂度:O(n)

稳定性:稳定

适用场合:数组量大且较无序

你可能感兴趣的:(C/C++,排序,归并排序)