数据结构——归并排序

目录

一、排序思想

二、排序过程

三、代码实现

1、递归写法

2、非递归写法


一、排序思想

该算法是采用分治法,将已有序的子序列合并,得到完全有序的序列。即先使每个子序列有序,再使最终序列有序。


二、排序过程

1、对无序数组进行递归分解(这里只是递归中的递推过程)

2、归并:将两个区间数据进行逐一比较,较小的尾插进新数组(这里是递归中的回归)

注:

1、所有的递归分解完成后才开始回归归并(即要分解到最小区间)

2、子区间排序过程其实是在比较尾插环节完成,一直归并到完整数组才完成最终排序

3、如下图解以及代码实现都是排成升序


三、代码实现

1、递归写法

复制代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

//打印
void Print(int* a, int n)
{
	for (int i = 0; i < n; i++)
	{
		printf("%d ", a[i]);
	}
	printf("\n");
}

//归并子函数
void _MergeSort(int* a, int begin, int end, int* tmp)
{
	if (begin >= end)
	{
		return;
	}

	int mid = (begin + end) / 2;
	//递归排序
	//[begin,mid] [mid+1,end]
	_MergeSort(a, begin, mid, tmp);
	_MergeSort(a, mid+1, end, tmp);
	//递归中递推过程完成,开始回归归并
	int begin1 = begin, end1 = mid;
	int begin2 = mid + 1, end2 = end;
	int i = begin;
	while (begin1 <= end1 && begin2 <= end2)//闭区间
	{
		//逐一比较,小的尾插进tmp
		if (begin1 < begin2)
		{
			tmp[i++] = a[begin1++];
		}
		else
		{
			tmp[i++] = a[begin2++];
		}
	}
	//到此有一组归并完成,有一组可能没有完成,但不知是哪一组
	//暴力排除
	while(begin1 <= end1)
	{
		tmp[i++] = a[begin1++];
	}
	while(begin2 <= end2)
	{
		tmp[i++] = a[begin2++];
	}
	//拷贝(并非一次性拷贝,而是分段拷贝,递归的每一次回归都拷贝一次)
	//每一次回归拷贝过程的区间可能都不同,begin、end是变化的,如下的begin不可少
	memcpy(a + begin, tmp + begin, sizeof(int) * (end - begin + 1));
}

//归并
void MergeSort(int* a, int n)
{
	int* tmp = (int*)malloc(n * sizeof(int));
	if (tmp == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}
	_MergeSort(a, 0, n - 1, tmp);
	free(tmp);
	tmp = NULL;
}

int main()
{
	int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
	MergeSort(arr, 10);
	Print(arr, 10);

	return 0;
}

2、非递归写法

复制代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

//打印
void Print(int* a, int n)
{
	for (int i = 0; i < n; i++)
	{
		printf("%d ", a[i]);
	}
	printf("\n");
}

//归并------非递归
void MergeSortNonR(int* a, int n)
{
	int* tmp = (int*)malloc(n * sizeof(int));
	if (tmp == NULL)
	{
		perror("malloc fail");
		return;
	}
	int gap = 1;//gap是区间跨度
	while (gap < n)
	{
		//一层归并,遍历
		for (int i = 0; i < n; i += gap * 2)
		{
			int begin1 = i, end1 = i + gap - 1;//区间1
			int begin2 = i + gap, end2 = i + 2 * gap - 1;//区间2
			//避免越界,修正
			if (end1 >= n || begin2 >= n)
			{
				break;
			}
			if (end2 >= n)
			{
				end2 = n - 1;
			}
			//开始归并
			int j = i;
			while (begin1 <= end1 && begin2 <= end2)
			{
				if (begin1 < 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));
		}
		gap = gap * 2;
	}


	free(tmp);
	tmp = NULL;
}

int main()
{
	int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
	MergeSortNonR(arr, 10);
	Print(arr, 10);

	return 0;
}

感谢阅读,本文如有疏漏不当之处,烦请各位指正。

相关推荐
2601_967760787 小时前
2026年PDF压缩与页码添加工具技术实测:性能、算法与本地化适配深度对比
算法·pdf
不会就选b7 小时前
算法日常・每日刷题--<贪心>7
数据结构·算法·leetcode
moonrailgun8 小时前
用 Node.js 复刻 Codex Astra 的终端星光
前端·javascript·算法
罗西的思考8 小时前
[Agent Memory / 强化学习] MemPO源码学习笔记 ---(1)--- 总体
人工智能·算法·机器学习
lvwangshu9 小时前
图论:LCA、树的直径、树的重心、二分图与 Tarjan 缩点
算法·图论
爱吃苹果的日记本9 小时前
数据结构第一课
c语言·数据结构·数据库·学习·c#
张小姐的猫10 小时前
【AI大模型接入SDK】 —— Gemini接入封装
android·数据结构·数据库·c++·人工智能·python
302wanger10 小时前
干与湿:AI 拿走脑力之后,人剩下什么
算法
计算机编程-吉哥11 小时前
脑肿瘤MRI智能识别系统:基于深度学习的像素级脑肿瘤语义分割平台【计算机毕业设计选题推荐】
人工智能·python·深度学习·算法·毕业设计·课程设计·大数据毕业设计选题推荐
用户2049375549511 小时前
端侧语音部署踩坑:模型能跑不等于终端真的能用
后端·算法