【排序】归并排序(C语言实现)

这篇具有很好参考价值的文章主要介绍了【排序】归并排序(C语言实现)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。




1. 递归版的归并排序


1.1 归并排序的思想

归并排序(MERGE - SORT)是建立在归并操作上的一种有效的排序算法, 该算法是采用分治法(Divide andConquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。 归并排序核心步骤:
【排序】归并排序(C语言实现),c语言,算法,排序算法
【排序】归并排序(C语言实现),c语言,算法,排序算法

这里我们先介绍一下递归版本的归并排序的思想:

  • 我们需要先创建一个临时数组,用来将需要排序的数组归并到这个临时数组里面去,然后再将这个数组拷贝到原数组中去,这样就完成了排序的过程。

2. 递归版的归并排序的实现

具体实现方式如下:

void Sub_MergeSort(int* a, int* tmp, int begin, int end)
{
	if (begin >= end - 1) // 我控制的是左闭右开区间
		return;

	int key = (begin + end) / 2;
	// [left,key + 1) [key,end) 左闭右开的空间一定要控制好
	int begin1 = begin, end1 = key;
	int begin2 = key, end2 = end;
	
	Sub_MergeSort(a, tmp, begin1, end1);
	Sub_MergeSort(a, tmp, begin2, end2);

	// 归并过程
	int indix = begin;
	while (begin1 < end1 && begin2 < end2)
	{
		if (a[begin1] <= a[begin2])
		{
			tmp[indix++] = a[begin1++];
		}
		else
		{
			tmp[indix++] = a[begin2++];
		}
	}
	while (begin1 < end1)
	{
		tmp[indix++] = a[begin1++];
	}
	while (begin2 < end2)
	{
		tmp[indix++] = a[begin2++];
	}

	// 将tmp数组中的元素拷贝到元素中
	memmove(a + begin, tmp + begin, (end - begin)*sizeof(int));
}


void MergeSort(int* a, int n)
{
	
	int* tmp = (int*)malloc(sizeof(int) * n);
	if (tmp == NULL)
	{
		perror("malloc fail\n");
		return;
	}
	// 因为这里开一次空间就够用了,所以递归过程我们还是要写成一个子函数来完成
	Sub_MergeSort(a, tmp, 0, n);

	free(tmp);
	tmp = NULL;
}


2. 非递归版的归并排序


所以在平时我们要使用归并排序时,使用递归版的完全够用了。但由于现在还在学习阶段,所以掌握一下非递归版的归并排序还是有必要的。

把递归改成非递归,这个怎么处理呢?可以像我们之前讲的快速排序的非递归一样使用栈吗?

这里实现非递归的归并排序使用栈其实不是很好的方式,反而会使问题变复杂。

【排序】归并排序(C语言实现),c语言,算法,排序算法
所以我们就得想其他办法:

可以这样:
【排序】归并排序(C语言实现),c语言,算法,排序算法
但是这里需要注意两种情况:
【排序】归并排序(C语言实现),c语言,算法,排序算法
这里不控制好边界的话,很容易就造成越界了,这里我分享两种控制边界的方式,细节我写在注释里了:

方式一:

// 归并排序 -- 非递归
void MergeSortNonR(int* a, int n)
{
	int* tmp = (int*)malloc(sizeof(int) * n);
	if (tmp == NULL)
	{
		perror("malloc fail\n");
		return;
	}

	int gap = 1;
	while (gap < n)
	{
		for (int i = 0;i < n;i = 2 * gap + i)
		{
			int begin1 = i, end1 = i + gap - 1; // 定义每次归并时的第一组数据
			int begin2 = i + gap, end2 = i + 2 * gap - 1; // 定义每次归并时的第二组数据

			if (begin2 >= n) // 如果第二组不存在了,这一趟就不用归并了
			{
				break;
			}

			if (end2 >= n) // 如果存在第二组,但第二组的末尾越界了,应该调整一下
			{
				end2 = n - 1;
			}

			// 归并过程
			int indix = i;
			while (begin1 <= end1 && begin2 <= end2)
			{
				if (a[begin1] < a[begin2])
				{
					tmp[indix++] = a[begin1++];
				}
				else
				{
					tmp[indix++] = a[begin2++];
				}
			}
			while (begin1 <= end1)
			{
				tmp[indix++] = a[begin1++];
			}
			while (begin2 <= end2)
			{
				tmp[indix++] = a[begin2++];
			}

			// 将tmp数组拷贝回原数组
			memcpy(a + i, tmp + i, (end2 - i + 1) * sizeof(int));
		}
		gap *= 2;
	}

	free(tmp);
	tmp = NULL;
}


方式二:文章来源地址https://www.toymoban.com/news/detail-782627.html

void MergeSortNonR2(int* a, int n)
{
	int* tmp = (int*)malloc(sizeof(int) * n);
	if (tmp == NULL)
	{
		perror("malloc fail\n");
		return;
	}

	int gap = 1;
	while (gap < n)
	{
		int j = 0;
		for (int i = 0;i < n;i += 2 * gap)
		{
			int begin1 = i, end1 = i + gap - 1;
			int begin2 = i + gap, end2 = i + 2 * gap - 1;

			// end1 >= n - 1 和begin2 >= n 都代表没有第二组,所以第二组就不用参与归并过程
			if (end1 >= n)
			{
				end1 = n - 1;

				// 此时begin2和end2一定是越界的
				// 我们手动让这段空间不存在
				begin2 = n;
				end2 = n - 1;
			}
			else if (begin2 >= n)
			{
				// 我们手动让这段空间不存在
				begin2 = n;
				end2 = n - 1;
			}
			else if (end2 >= n) // 此时end1 和 begin2都没有越界
			{
				end2 = n - 1;
			}

			// 归并过程
			while (begin1 <= end1 && begin2 <= end2)
			{
				if (a[begin1] <= a[begin2])
				{
					tmp[j++] = a[begin1++];
				}
				else
				{
					tmp[j++] = a[begin2++];
				}
			}
			while (begin1 <= end1)
			{
				tmp[j++] = a[begin1++];
			}
			while (begin2 <= end2)
			{
				tmp[j++] = a[begin2++];
			}
		}
		memcpy(a, tmp, sizeof(int) * n);
		gap *= 2;
	}

	free(tmp);
	tmp = NULL;
}

到了这里,关于【排序】归并排序(C语言实现)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 排序算法-归并排序(含C语言代码示例)

            归并排序是一种基于分治思想的经典排序算法,其主要思想是将待排序的数组分割成两个子数组,分别对这两个子数组进行递归排序,然后将排好序的子数组合并起来得到最终有序数组。整个归并排序的过程可以分为三个步骤:分割、排序和合并。         首

    2024年01月16日
    浏览(42)
  • 【数据结构与算法】归并排序详解:归并排序算法,归并排序非递归实现

    归并排序是一种经典的排序算法,它使用了分治法的思想。下面是归并排序的算法思想: 递归地将数组划分成较小的子数组,直到每个子数组的长度为1或者0。 将相邻的子数组合并,形成更大的已排序的数组,直到最终得到一个完全排序的数组。 归并排序的过程可以分为三

    2024年01月22日
    浏览(70)
  • 【排序】归并排序(C语言实现)

          归并排序(MERGE - SORT)是建立在归并操作上的一种有效的排序算法, 该算法是采用分治法(Divide andConquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为

    2024年02月02日
    浏览(37)
  • 【排序算法】 归并排序详解!深入理解!思想+实现!

    🎥 屿小夏 : 个人主页 🔥个人专栏 : 算法—排序篇 🌄 莫道桑榆晚,为霞尚满天! ​ 什么是归并?通过归并排序就能让数据有序?分治法是怎么在归并排序上应用的?本文将对归并排序进行细致入微的讲解,庖丁解牛般让你彻底明白归并排序! 归并排序(MERGE-SORT)是建

    2024年02月08日
    浏览(44)
  • 八大排序算法之归并排序(递归实现+非递归实现)

    目录 一.归并排序的基本思想 归并排序算法思想(排升序为例) 二.两个有序子序列(同一个数组中)的归并(排升序) 两个有序序列归并操作代码: 三.归并排序的递归实现 递归归并排序的实现:(后序遍历递归) 递归函数抽象分析:  四.非递归归并排序的实现 1.非递归归并排序算法思想

    2024年02月03日
    浏览(42)
  • 归并排序算法(Java实现)

    也称 合并排序算法 ,是将两个或两个以上的有序数据序列合并成一个新的有序数据序列。该算法采用分治法(Divide and Conquer)的思想,将待排序的序列分成若干个子序列,分别对子序列进行排序,然后将有序的子序列合并成一个大的有序序列 注:将几个有序队列合并成一个

    2024年01月17日
    浏览(38)
  • 【排序算法】 归并排序详解!深入理解!思想+源码实现!

    🎥 屿小夏 : 个人主页 🔥个人专栏 : 算法—排序篇 🌄 莫道桑榆晚,为霞尚满天! ​ 什么是归并?通过归并排序就能让数据有序?分治法是怎么在归并排序上应用的?本文将对归并排序进行细致入微的讲解,庖丁解牛般让你彻底明白归并排序! 归并排序(MERGE-SORT)是建

    2024年02月06日
    浏览(46)
  • 【数据结构与算法】:非递归实现快速排序、归并排序

    🔥 个人主页 : Quitecoder 🔥 专栏 :数据结构与算法 上篇文章我们详细讲解了递归版本的快速排序,本篇我们来探究非递归实现快速排序和归并排序 快速排序的非递归实现主要依赖于栈(stack)来模拟递归过程中的函数调用栈。递归版本的快速排序通过递归调用自身来处理子

    2024年03月24日
    浏览(55)
  • [数据结构 -- 手撕排序算法第七篇] 递归实现归并排序

    目录 1、归并的思想 2、归并排序的思想 2.1 基本思想 2.2 图解分析 3、归并排序递归版本代码实现 3.1 代码解析 3.2 注意事项 3.2.1错误划分:[begin, mid-1],[mid, end] 3.2.2 正确划分:[begin, mid], [mid+1, end] 4、归并排序的测试 5、时间复杂度、空间复杂度分析 5.1 时间复杂度 5.2 空间复杂

    2024年02月16日
    浏览(50)
  • 排序篇:归并排序的递归,非递归以及计数排序的实现(C语言)

    目录 一:归并排序 (1)归并排序的基本思想 (2)递归版本 ①实现思路 ②合并 ③递归实现有序 ④最终代码 (3)非递归版本 ①实现思路 ②控制分组 ③最终代码 (4)时间,空间复杂度分析 (5)小结 二:计数排序 (1)计数排序的基本思想 (2)实现思路 (3)图解加最终代码 (4)时间,空间复杂

    2024年02月04日
    浏览(68)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包