归并排序算法是在分治算法基础上设计出来的一种排序算法,它可以对指定序列完成升序(由小到大)或降序(由大到小)排序,对应的时间复杂度为O(nlogn)。


(1)算法思路

归并排序算法实现排序的思路是:

1. 将整个待排序序列划分成多个不可再分的子序列,每个子序列中仅有 1 个元素;

2. 所有的子序列进行两两合并,合并过程中完成排序操作,最终合并得到的新序列就是有序序列。


(2)动图演示

归并排序算法


(3)归并排序的特性总结:

 1. 归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。

 2. 时间复杂度:O(N*logN)

 3. 空间复杂度:O(N)

 4. 稳定性:稳定


(4)C语言代码实现如下:

#include<stdio.h>
#include<stdlib.h>

void Merge(int arr[], int tmp[], int start,int mid, int end)//合并小组并排序
{
	int i = start;//i标识//左小组的第一个元素位置
	int j = mid + 1;//j标识//右小组的第一个元素位置
	int k = start;//tmp当前小组存放的起始位置
	while (i < mid + 1 && j < end + 1)//左小组越界或右小组越界才能退出
	{
		if (arr[i] <= arr[j])
		{
			tmp[k++] = arr[i++];
		}
		else
		{
			tmp[k++] = arr[j++];
		}
	}

	while (j < end + 1)//如果右边小组没有越界
	{
		tmp[k++] = arr[j++];
	}

	while (i < mid + 1)//如果左边小组没有越界
	{
		tmp[k++] = arr[i++];
	}//哦哦就是补齐了,把数组放到新的那个临时数组中去了

	for (i = start; i <= end; i++)
	{
		arr[i] = tmp[i];
	}//至此,原来的数组已经排序完毕
}

void MergeS(int arr[], int tmp[], int start, int end)//划分小组,现在没有end.
{
	if (start < end)
	{
		int mid = (start+end)/2;
		MergeS(arr, tmp, start, mid);
		MergeS(arr, tmp, mid + 1, end);//自我递归调用
		Merge(arr, tmp, start, mid, end);//现在就全部排号
	}
}//就是递归调用呗

void MergeSort(int arr[], int len)
{
	int *tmp = (int *)malloc(sizeof(int)*len);//开了一个排序后结果保存的临时数组
	MergeS(arr, tmp, 0, len - 1);//嵌套调用
	free(tmp);
}

int main()
{
	int arr[] = { 12, 3, 21, 32, 1, 34, 12, 35, 34 };//举例子
    //int s,arr[100];
    //scanf("%d",&s);
    //for(int i=0;i<s;i++)
    //{
     //   scanf("%d ",&arr[i]);
    //}
	int len = sizeof(arr) / sizeof(arr[0]);
	MergeSort(arr, len);
	for (int i = 0; i < len; i++)
	{
		printf("%d  ", arr[i]);
	}
	printf("\n");
	return 0;
}

如果我们编译并运行上述程序,那么它应该产生以下结果:

1  3  12  12  21  32  34  34  35


作业:
1719 数据结构-归并排序
点赞(0)

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

Dotcpp在线编译      (登录可减少运行等待时间)