C语言归并排序(合并排序)算法以及代码

合并排序是采用分治法,先将无序序列划分为有序子序列,再将有序子序列合并成一个有序序列的有效的排序算法。

原理:先将无序序列利用二分法划分为子序列,直至每个子序列只有一个元素(单元素序列必有序),然后再对有序子序列逐步(两两)进行合并排序。合并方法是循环的将两个有序子序列当前的首元素进行比较,较小的元素取出,置入合并序列的左边空置位,直至其中一个子序列的最后一个元素置入合并序列中。最后将另一个子序列的剩余元素按顺序逐个置入合并序列尾部即可完成排序。整体过程如下图:

 两个有序子序列合并的原理如下图:

代码:递归式实现

#include <malloc.h>
#include <stdlib.h>
void mergesort(int A[],int n)  //合并排序的递归主体
{
    void merge(int A[], int L[], int R[], int l, int r);  //声明merge函数
    if(n>1)    //多于一个元素才需要排序
    {
        int mid=n/2;
        int *left=(int*)malloc(sizeof(int)*mid);
        int *right=(int*)malloc(sizeof(int)*(n-mid));
        for(int i=0;i<mid;i++)
            left[i]=A[i];       //建立临时数组存储左半部分序列
        for(int j=mid;j<n;j++)
            right[j-mid]=A[j];  //建立临时数组存储右半部分序列
 
        mergesort(left,mid);    //调用自身对左半部分进行合并排序
        mergesort(right,n-mid); //调用自身对右半部分进行合并排序
        merge(A,left,right,mid,n-mid);   //两个有序序列的合并操作,封装为函数
        free(left);
        free(right);
    }
}
 
void merge(int A[],int L[],int R[],int l,int r)  //两个有序序列L、R合并为A,l,r分别为L,R的长度
{
    int i=0,j=0,k=0;
    while(i<l&&j<r)  //两个子序列首元素做比较,小者取出置入父序列
    {
        if(L[i]<=R[j])
            A[k++]=L[i++];
        else
            A[k++]=R[j++];
    }
    while(i<l)       //将左半部分剩余元素置入父序列
    {
        A[k++]=L[i++];
    }
    while(j<r)       //将右半部分剩余元素置入父序列
    {
        A[k++]=R[j++];
    }
}

改进:非递归式实现

递归式的实现方法,当输入规模增大时,会表现出效率低的缺点。且在排序过程中会不断的开辟临时空间,容易造成内存混乱。

void mergesort(int A[], int n){    //非递归实现。只开辟一个大小与待排序数组相同的存储数组,排序过程中直接在该数组上进行操作。不反复开辟临时数组
	int step;   
	int *p, *q, *t;
	int i, j, k, len1, len2;
	int *temp;  
	step = 1;      //初始步长为1,即将单个元素作为有序子序列进行合并
	p = A;
	q = (int*)malloc(sizeof(int)*n);  //q为临时开辟的空间,用来存储已排序序列,大小为待排序数组的长度
	temp = q;                              //temp与q指向同一段内存,留作最后释放内存空间时使用,因为q指针在后面排序操作中可能会改变指向
	while (step<n)
	{
		i = 0;
		j = i + step;
		k = i;                             //k用作临时数组的下标
		len1 = i + step < n ? i + step : n;   //len1表示有序序列1的下标上限
		len2 = j + step < n ? j + step : n;   //len2表示有序序列2的下标上限
		while (i<n)
		{
			while (i<len1&&j<len2)        //两个子序列首元素做比较,小者取出置入父序列
			{
				q[k++] = p[i]<p[j] ? p[i++] : p[j++];
			}
			while (i<len1)                //将子序列1的剩余元素置入父序列
			{
				q[k++] = p[i++];
			}
			while (j<len2)                //将子序列2的剩余元素置入父序列
			{
				q[k++] = p[j++];
			}
			i = j;                        //j经过自增变为len2,然后赋值给i
			j = i + step;                 //i被赋值为len2,加上步长再赋值给j
			k = i;                        
			len1 = i + step < n ? i + step : n;
			len2 = j + step < n ? j + step : n;
		}
		step *= 2;   //步长翻倍,即将原步长2倍个数的数组元素作为有序子序列进行合并
		t = p;       //t作为临时指针变量,用于交换p和q的指针指向
		p = q;       //将p指针指向经过一轮合并排序后的临时数组
		q = t;       //将q指针指向原数组
	}
	if (A != p){     //如果最终p指针的指向改变为临时数组,则将完成排序的数组拷贝至原数组
		memcpy(A, p, sizeof(int)*n);
	}
	free(temp);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/258691.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【VScode和Leecode的爱恨情仇】command ‘leetcode.signin‘ not found

文章目录 一、关于command ‘leetcode.signin‘ not found的问题二、解决方案第一&#xff0c;没有下载Nodejs&#xff1b;第二&#xff0c;有没有在VScode中配置Nodejs第三&#xff0c;力扣的默认在VScode请求地址中请求头错误首先搞定配置其次搞定登入登入方法一&#xff1a;…

netty线程调度定制

1、netty的线程调度问题 在netty的TCP调度中&#xff0c;线程的调度封装在NioEventLoopGroup中&#xff0c;线程执行则封装在NioEventLoop中。 线程调度规则封装在MultithreadEventExecutorGroup的next方法中&#xff0c;这个方法又封装了EventExecutorChooserFactory&#xf…

ArkTS @Observed、@ObjectLink状态装饰器的使用

作用 Observed、ObjectLink装饰器用于在涉及嵌套对象或者数组元素为对象的场景中进行双向数据同步。 状态的使用 1.嵌套对象 我们将父类设置为Observed状态&#xff0c;这个时候&#xff0c;子应该设置ObjectLink才能完成数据的双向绑定&#xff0c;所以我们构建一个组件&…

控制理论simulink+matlab

这里写目录标题 根轨迹二级目录三级目录 根轨迹 z [-1]; %开环传递函数的零点 p [0 -2 -3 -4]; %开环传递函数的系统极点 k 1; %开环传递函数的系数&#xff0c;反映在比例上 g zpk(z,p,k); %生成开环传递函数%生成的传递函数如下 % (s1) % -------------…

Vue3-23-组件-依赖注入的使用详解

什么是依赖注入 个人的理解 &#xff1a; 依赖注入&#xff0c;是在 一颗 组件树中&#xff0c;由 【前代组件】 给 【后代组件】 提供 属性值的 一种方式 &#xff1b;这种方式 突破了 【父子组件】之间通过 props 的方式传值的限制&#xff0c;只要是 【前代组件】提供的 依…

「Qt Widget中文示例指南」如何创建一个计算器?(三)

Qt 是目前最先进、最完整的跨平台C开发工具。它不仅完全实现了一次编写&#xff0c;所有平台无差别运行&#xff0c;更提供了几乎所有开发过程中需要用到的工具。如今&#xff0c;Qt已被运用于超过70个行业、数千家企业&#xff0c;支持数百万设备及应用。 本文将展示如何使用…

【开源GIS】如何高效地学习GIS开源项目?一上来就读源码你就输了!

目录 &#x1f525;前言Step 1: 熟悉项目Step 2: Hello worldStep 3: 深入了解和使用Step 4: 可以看源码了&#xff01;Step 5: API 二次封装Step 6: 持续关注和学习 &#x1f525;前言 都知开源好&#xff0c;只看源码看不懂&#xff0c;是俺太菜了&#xff1f;no no no&#…

kubeadm方式重置k8s集群

以kubeadm方式部署的k8s&#xff0c;当出现问题&#xff0c;排查解决的难度会非常大&#xff0c;如果是实验环境&#xff0c;直接进行集群重置即可&#xff0c;如果是生产环境&#xff0c;如果集群已经崩掉了&#xff0c;而且短时间时间内无法定位原因的情况的下&#xff0c;建…

Ansible(一)

Ansible: 远程操作主机功能&#xff1a; 自动化运维&#xff08;playbook剧本YAML&#xff09; 是基于Python开发的配置管理应用部署攻具&#xff0c;在自动化运维当中&#xff0c;现在是异军突起 Ansible能批量配置&#xff0c;部署&#xff0c;管理上千台主机&#xff0c…

基于vite 初始化vue3项目并引入Vue Router和Ant Design Vue

基于vite 初始化vue3项目并引入常用的功能、组件。 Vue RouterAnt Design Vue 系列文章指路&#x1f449; 系列文章-基于Vue3创建前端项目并引入、配置常用的库和工具类 文章目录 创建ViteVue项目创建并运行WebStorm无法识别&#xff0c;需要在vite.config.js中定义alias 引入…

GNSS模块在野外探险中的应用

野外探险是一项令人兴奋的活动&#xff0c;而GNSS&#xff08;全球导航卫星系统&#xff09;模块的广泛应用为探险者提供了精准的导航、位置跟踪和安全保障。本文将深入探讨GNSS模块在野外探险中的应用&#xff0c;以及它如何改变和增强探险体验。 精准导航与路径规划&#xf…

基于SpringBoot的大病保险管理系统 JAVA简易版

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 系统配置维护2.2 系统参保管理2.3 大病保险管理2.4 大病登记管理2.5 保险审核管理 三、系统详细设计3.1 系统整体配置功能设计3.2 大病人员模块设计3.3 大病保险模块设计3.4 大病登记模块设计3.5 保险审核模块设计 四、…

VS Code配置Go语言开发环境

提示&#xff1a;首先这是一个新型语言&#xff0c;最好把vscode更新到最新版。 1&#xff1a;去官网下载Go语言编译器&#xff0c;之后配置到系统环境中&#xff0c;能看到版本就行。 2&#xff1a;创建一个文件夹&#xff0c;存放go的工具文件&#xff0c;我的在D:\GoFile\G…

职场如何与不同级别的领导打交道?学会3个小妙招吃遍天下

职场如何与不同级别的领导打交道&#xff1f;学会3个小妙招吃遍天下 简介 刚步入职场的时候&#xff0c;很多新人小白会患上权威恐惧症&#xff0c;简单来说就是害怕与领导打交道&#xff0c;职位越大的领导越害怕。有领导在的地方有多远就躲多远&#xff0c;更别说主动去找领…

嵌入式串口输入详细实例

学习目标 掌握串口初始化流程掌握串口输出单个字符掌握串口输出字符串掌握通过串口printf熟练掌握串口开发流程学习内容 需求 串口循环输出内容到PC机。 串口数据发送 添加Usart功能。 首先,选中Firmware,鼠标右键,点击Manage Project Items 接着,将gd32f4xx_usart.c添…

[PyTorch][chapter 8][李宏毅深度学习][Back propagation]

前言&#xff1a; 反向传播算法(英:Backpropagation algorithm&#xff0c;简称:BP算法)是一种监督学习算法&#xff0c;常被用来训练多层感知机。 它用于计算梯度计算中&#xff0c;降低误差。 目录&#xff1a; 链式法则 模型简介&#xff08;Model&#xff09; 损失函…

【YOLOv8量化】普通CPU上加速推理可达100+FPS

NNCF介绍 OpenVINO2023版本衍生出了一个新支持工具包NNCF(Neural Network Compression Framework – 神经网络压缩框架)&#xff0c;通过对OpenVINO IR格式模型的压缩与量化更好的提升模型在OpenVINO框架上部署的推理性能&#xff0c;github。 https://github.com/openvinoto…

银河麒麟v10 安装mysql 8.35

银河麒麟v10 安装mysql 8.35 1、下载Mysql安装包2、安装Mysql 8.352.1、安装依赖包2.2、安装Mysql2.3、安装后配置 1、下载Mysql安装包 访问官网下载链接 链接: https://dev.mysql.com/downloads/mysql/ 选择如下 点击下载按钮 下载安装包 2、安装Mysql 8.35 官方安装文档…

AWS Linux安装桌面并远程访问

文章目录 小结问题及解决参考 小结 在AWS Linux安装了桌面并进行远程访问。 问题及解决 需要使用过程桌面访问AWS Linux&#xff0c;这里在AWS服务器安装并使用Amazon Linux 2 MATE desktop。 检查OS版本&#xff1a; [ec2-userip-10-0-3-241 ~]$ grep PRETTY_NAME /etc/o…

算法设计与分析2023秋-头歌实验-实验七 动态规划

文章目录 第1关&#xff1a;数塔问题任务描述相关知识编程要求解题思路测试说明参考答案 第2关&#xff1a;最长公共子序列任务描述相关知识编程要求解题思路&#xff1a;测试说明参考答案 第3关&#xff1a;求序列-2 11 -4 13 -5 -2的最大子段和任务描述相关知识编程要求解题思…