排序嘉年华———归并排序

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

一.归并是什么?

相信朋友们应该做过一类题,合并两个有序数组,在链表里也有合并两个单链表的oj题,那我们稍微回顾一下

题目一:合并有序数组

普通思路:
1.定义一个第三方数组,用来临时归并排序
2.分别比较两个数组,小者先放进临时数组中
3.补充未排完的数组
4.将临时数组的值拷贝进返回数组nums1
void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) {
    int sum[m+n];
    int i=0,j=0,count=0;

    //比较取小尾插
    while(i<m&&j<n)
    {
        if(nums1[i]<=nums2[j])
        {
            sum[count++]=nums1[i++];
        }
        else
        {
            sum[count++]=nums2[j++];
        }
    }

    //补充
    while(i<m)
    {
       sum[count++]=nums1[i++];
    }
     while(j<n)
    {
       sum[count++]=nums2[j++];
    }

   memcpy(nums1,sum,sizeof(int)*(m+n));
}

题目二:合并有序链表

普通思路:
1.定义并维护指针head  tail
2.判断两种特殊情况
3.循环比较尾插
4.若有未链接的连结则直接尾插
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
    struct ListNode *head=NULL, *tail=NULL;
    //两种特殊情况
    if (list1 == NULL)
        return list2;
    if (list2 == NULL)
        return list1;

    while (list1 && list2) {
        if (list1->val <= list2->val) {
            //初始状态判定
            if (tail == NULL)
                head = tail = list1;

            else {
                tail->next = list1;
                tail = list1;
            }
            if (list1)
                list1 = list1->next;

        } else {
            //初始状态判定
            if (tail == NULL)
                head = tail = list2;

            else {
                tail->next = list2;
                tail = list2;
            }
            if (list2)
                list2 = list2->next;
        }
    }
    //补充
    if(list1) tail->next=list1;
    else tail->next=list2;
    return head;
}

二.归并排序

字面意思,归并排序是通过将数据分别归并比较最终成为有序
排序嘉年华———归并排序,排序算法,算法,数据结构,学习方法,visual studio,笔记,经验分享
建立一个临时数组,然后将数据两两归并放入临时数组,最终将有序数组拷贝回目标数组中

1.递归式归并

  • 首先动态开辟一个临时数组tmp
void Mergesort(int* a, int n)
{
	int* tmp = (int*)malloc(sizeof(int) * n);
	if (tmp == NULL)
	{
		perror("malloc fail");
	}
	_Mergesort(a, 0, n - 1, tmp);
	
	free(tmp);
}
  • 然后编写子程序_Mergesort
void _Mergesort(int* a, int begin, int end, int* tmp)

四个参数,目标无序数组,目标起始下标,目标结束下标,已开辟的数组

  • 确定递归结束条件,归并的区间<=1时则可视为有序
if (begin >= end)
		return;
  • 分离出归并区间,取中间下标,递归式分离
//分离[begin1,end1][begin2,end2]
	int mid = (begin + end) / 2;
	int begin1 = begin, end1 = mid;
	int begin2 = mid + 1, end2 = end;
	_Mergesort(a, begin1, end1, tmp);
	_Mergesort(a, begin2, end2, tmp);
  • 开始归并,这里的小细节是递归一次拷贝一组,边排边拷贝,不然可能导致数据丢失
//归并
	int i = begin;
	while (begin1<=end1&&begin2<=end2)
	{
		if (a[begin1] <= a[begin2])
		{
			tmp[i++] = a[begin1++];
		}
		else
		{
			tmp[i++] = a[begin2++];
		}
	}
	while (begin1 <= end1)
	{
		tmp[i++] = a[begin1++];
	}
	while (begin2 <= end2)
	{
		tmp[i++] = a[begin2++];
	}

	memcpy(a+begin, tmp+begin, sizeof(int) * (end - begin + 1));

程序编写完成,测试一下

void test()
{
	int a[11] = { 9,6,7,3,1,5,7,10,0,0,1 };
	Mergesort(a, 11);
	for (size_t i = 0; i < 11; i++)
	{
		printf("%d ", a[i]);

	}
}

排序嘉年华———归并排序,排序算法,算法,数据结构,学习方法,visual studio,笔记,经验分享

2.非递归式的归并排序

非递归思路是由分散的每个数据两两归并,然后成倍增加归并个体的数量,如下图
排序嘉年华———归并排序,排序算法,算法,数据结构,学习方法,visual studio,笔记,经验分享

  • 先将组内数量设置为gap=1
int gap = 1;
	while (gap < n)
	{

	//...
		gap *= 2;
	}
  • 分理待归并数组
for (size_t i = 0; i < n ;i+=2*gap)
		{
			//分出两组区域
			int begin1 = i, end1 = i + gap - 1;
			int begin2 = i + gap, end2 = i + 2 * gap - 1;
			//...
		}
  • 如果是单纯end1或begin2越界出错则直接跳出,如果end2出错那就直接将end2的边界处理为n-1
// 边界的处理
			if (end1 >= n || begin2 >= n)
			{
				break;
			}

			if (end2 >= n)
			{
				end2 = n - 1;
			}
  • 然后开始基本环节归并并拷贝回目标数组
int j = begin1;
			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 + i, tmp + i, sizeof(int) * (end2-i+1));
  • 最后释放临时数组
    free(tmp);
    测试一下:
void test()
{
	int a[11] = { 9,6,7,3,1,5,7,10,0,0,1 };
	MergeNRsort(a, 11);
	for (size_t i = 0; i < 11; i++)
	{
		printf("%d ", a[i]);

	}
}

排序嘉年华———归并排序,排序算法,算法,数据结构,学习方法,visual studio,笔记,经验分享
两个完整代码已上传码云:递归和非递归归并排序
排序嘉年华———归并排序,排序算法,算法,数据结构,学习方法,visual studio,笔记,经验分享
感谢大佬评论和建议文章来源地址https://www.toymoban.com/news/detail-796359.html

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

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

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

相关文章

  • 数据结构和算法笔记4:排序算法-归并排序

    归并排序算法完全遵循分治模式。直观上其操作如下: 分解:分解待排序的n个元素的序列成各具n/2个元素的两个子序列。 解决:使用归并排序递归地排序两个子序列。 合并:合并两个已排序的子序列以产生已排序的答案。 我们直接来看例子理解算法的过程,下面是要排序

    2024年01月21日
    浏览(64)
  • 数据结构与算法—归并排序&计数排序

    目录 一、归并排序 1、主函数 2、递归实现 3、优化递归  4、非递归实现 5、特性总结: 二、计数排序 1、代码: 2、特性总结: 三、各种排序总结 时间空间复杂度汇总  基本思想: 归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用 分治法 的一个非常典型的

    2024年02月04日
    浏览(48)
  • 数据结构算法--5 归并排序

    我们先看一下归并排序是怎么归并的  两个有序列表,有low指针指向2,high指针指向6,mid指针指向9 再建一个新列表,12,所以1放到列表,右指针右移一位,再比较2和3,2放入列表,左指针右移一位,以此类推,肯定有一部分列表率先没有数,这时将另一列表直接append进入新

    2024年02月11日
    浏览(48)
  • 数据结构与算法:归并排序

    在讲解归并排序前,我们先看到一个问题: 对于这样两个有序的数组,如何将它们合并为一个有序的数组? 在此我们处理这个问题的思路就是:开辟一个新的数组,然后分别安置一个指针在左右数组,利用指针遍历数组,每次对比将比较小的那个元素插入到数组的尾部。 像

    2024年01月21日
    浏览(46)
  • python算法与数据结构---排序和归并排序

    掌握归并排序的基本原理 使用python语言解答归并排序题目 原理及过程 将两个有序的数组合并成一个有序数组称为 从上往下分解:把当前区间一分为二,直至分解为若干个长度为1的子数组 从上往下的合并:两个有序的子区域两两向上合并; 体现了分治思想,稳定排序 复杂

    2024年01月21日
    浏览(72)
  • 【数据结构】排序算法(二)—>冒泡排序、快速排序、归并排序、计数排序

    👀 樊梓慕: 个人主页  🎥 个人专栏: 《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》 🌝 每一个不曾起舞的日子,都是对生命的辜负 目录 前言 1.冒泡排序 2.快速排序 2.1Hoare版 2.2占坑版 2.3前后指针版 2.4三数取中对快速排序的优化 2.5非递归版 3.归

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

    🔥 个人主页 : 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)
  • 【一起学数据结构与算法】几种常见的排序(插入排序、选择排序、交换排序、归并排序)

    排序是计算机内经常进行的一种操作,其目的是将一组 “无序” 的记录序列调整为 “有序” 的记录序列。分 内部排序 和 外部排序 ,若整个排序过程不需要访问外存便能完成,则称此类排序问题为内部排序。反之,若参加排序的记录数量很大,整个序列的排序过程不可能

    2023年04月09日
    浏览(46)
  • 【数据结构】- 排序(详细介绍几种排序算法!!!*直接插入排序,*希尔排序,*选择排序,*堆排序,*冒泡排序,*快速排序,*归并排序)

    排序无处不在,所谓排序,就是使一串记录,按照其中的某个或某些的大小,递增或递减的排列起来的操作。 内部排序 :数据元素全部放在内存中的排序。 外部排序 :数据元素太多不能同时放在内存中,根据排序过程的要求不能在内外存之间移动数据的排序。 今天

    2024年01月20日
    浏览(62)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包