排序算法 -归并排序

文章目录

  • 1. 归并排序(Merge Sort)
    • 1.1 简介
    • 1.2 归并排序的步骤
    • 1.3 归并排序c 语言实现
      • 代码说明
    • 1.4 时间复杂度
    • 1.5 空间复杂度
    • 1.6 动画

1. 归并排序(Merge Sort)

1.1 简介

归并排序(Merge Sort)是一种基于分治思想的排序算法,它的核心思想是将一个数组分成两个或多个子数组,分别对这些子数组进行排序,然后再将这些已排序的子数组合并成一个完整的、有序的数组。归并排序的主要特点是其稳定性和高效性。

1.2 归并排序的步骤

归并排序(Merge Sort)是一种基于分治思想的排序算法,它的核心思想是将一个数组分成两个或多个子数组,分别对这些子数组进行排序,然后再将这些已排序的子数组合并成一个完整的、有序的数组。归并排序的主要特点是其稳定性和高效性。

  1. 分解:将数组从中间(或按其他方式)分成两个或更多个子数组,直到每个子数组只包含一个元素(此时子数组自然有序)。

  2. 递归排序:递归地对每个子数组进行归并排序。由于每个子数组在分解过程中最终都会变成一个元素的数组(有序),因此递归的基准条件是子数组长度为1。

  3. 合并:将两个或更多个已排序的子数组合并成一个有序的数组。合并过程通常涉及比较两个子数组的元素,并按顺序将它们放入一个新的数组中。

1.3 归并排序c 语言实现

#include <stdio.h>
#include <stdlib.h>// 合并两个已排序的子数组
void merge(int arr[], int left, int mid, int right) {int n1 = mid - left + 1;int n2 = right - mid;// 创建临时数组int* L = (int*)malloc(n1 * sizeof(int));int* R = (int*)malloc(n2 * sizeof(int));// 拷贝数据到临时数组L[]和R[]for (int i = 0; i < n1; i++)L[i] = arr[left + i];for (int j = 0; j < n2; j++)R[j] = arr[mid + 1 + j];// 合并临时数组回到arr[left..right]int i = 0; // 初始化左子数组的起始索引int j = 0; // 初始化右子数组的起始索引int k = left; // 初始化合并后子数组的起始索引while (i < n1 && j < n2) {if (L[i] <= R[j]) {arr[k] = L[i];i++;} else {arr[k] = R[j];j++;}k++;}// 拷贝L[]的剩余元素(如果有)while (i < n1) {arr[k] = L[i];i++;k++;}// 拷贝R[]的剩余元素(如果有)while (j < n2) {arr[k] = R[j];j++;k++;}// 释放临时数组的内存free(L);free(R);
}// 归并排序的主函数
void mergeSort(int arr[], int left, int right) {if (left < right) {// 找到中间点int mid = left + (right - left) / 2;// 递归排序两个子数组mergeSort(arr, left, mid);mergeSort(arr, mid + 1, right);// 合并两个已排序的子数组merge(arr, left, mid, right);}
}// 打印数组
void printArray(int arr[], int size) {for (int i = 0; i < size; i++)printf("%d ", arr[i]);printf("\n");
}// 主函数
int main() {int arr[] = {12, 11, 13, 5, 6, 7};int arr_size = sizeof(arr) / sizeof(arr[0]);printf("Given array is \n");printArray(arr, arr_size);mergeSort(arr, 0, arr_size - 1);printf("\nSorted array is \n");printArray(arr, arr_size);return 0;
}

代码说明

  1. merge函数:这个函数负责合并两个已排序的子数组。它首先为两个子数组分配临时内存,然后将它们拷贝到临时数组中。接着,它比较两个临时数组的元素,并按顺序将它们拷贝回原数组。最后,它释放临时数组的内存。

  2. mergeSort函数:这是归并排序的主函数。它首先检查左索引是否小于右索引,如果是,则找到中间点,并递归地对左右两个子数组进行排序。排序完成后,它调用merge函数来合并两个已排序的子数组。

  3. printArray函数:这个函数用于打印数组的元素。

  4. main函数:这是程序的入口点。它定义了一个数组,计算其大小,打印原始数组,调用mergeSort函数对数组进行排序,然后打印排序后的数组。

编译并运行此程序,你将看到原始数组和排序后的数组的输出。

1.4 时间复杂度

归并排序的时间复杂度为O(n log n),这里的n代表数组的元素数量。这一结论源自归并排序的分治特性:

  1. 分解阶段:每次都将数组一分为二,直至每个子数组仅含一个元素。此分解过程需要log n层(因为每次都将问题规模减半)。

  2. 合并阶段:在合并两个已排序的子数组时,需要遍历这两个子数组的所有元素。在最坏情况下,每层合并的总操作数为n(尽管每层合并的实际操作数可能因子数组大小而异,但总操作数在n的量级上)。

1.5 空间复杂度

  1. 递归调用栈:虽然递归调用栈的空间复杂度与递归的深度相关,但在归并排序中,递归深度为log n(因为每次数组都被一分为二)。然而,这部分空间复杂度通常被视为“辅助空间”的一部分,且在实际分析中可能不被单独计算(特别是当它与n相比不显著时)。

  2. 合并时的临时数组:在合并两个已排序的子数组时,通常需要一个额外的、与较大子数组等大的临时数组来存储合并结果。在最坏情况下(即当两个子数组大小相近时),这个临时数组的大小为 n 2 \frac{n}{2} 2n近似为 n 2 \frac{n}{2} 2n,但在大O表示法中仍视为O(n))。

1.6 动画

merge

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

unity 一个物体随键盘上下左右旋转和前进的脚本

注意&#xff1a;脚本挂在gamaobject 上面 &#xff0c;操作对象的目标 this.gameObject 为操作对象 using System.Collections; using System.Collections.Generic; using UnityEngine;public class changePosition : MonoBehaviour {//操作对象的目标 this.gameObject 为操…

视频里的音频怎么提取出来成单独文件?音频提取照着这些方法做

在数字时代&#xff0c;视频与音频的分离与重组已成为日常需求之一。无论是出于制作背景音乐、保存讲座内容&#xff0c;还是编辑播客素材&#xff0c;提取视频中的音频并将其保存为单独文件都显得尤为重要。视频里的音频怎么提取出来成单独文件&#xff1f;本文将详细介绍几种…

React(一)

文章目录 项目地址一、创建第一个react项目二、JSX语法2.1 生成列表2.2 大括号识别JS的表达式2.3 列表循环array2.4 条件判断以及假值显示2.5 复杂条件渲染2.6 事件监听和绑定2.7 使用Fregments返回多个根标签2.8 多条件渲染2.9 导出子组件 三、组件3.1 设置组件3.2 props给子组…

记录一下在原有的接口中增加文件上传☞@RequestPart

首先&#xff0c;咱声明一下&#xff1a; RequestBody和 MultipartFile 不可以 同时使用&#xff01;&#xff01;&#xff01; 因为这两者预期的请求内容类型不同。RequestBody 预期请求的 Content-Type 是 application/json 或 application/xml&#xff0c;而 MultipartFile …

HTTPSOK ---助力阿里云免费 SSL 证书自动续期

目前许多用户面临着 SSL 证书过期续期的难题&#xff0c;尤其是对于阿里云的 免费 SSL 证书&#xff0c;每三个月需要手动申请和更新。为了帮助用户更轻松地管理 SSL 证书&#xff0c;现推出了强大的 HTTPSOK 服务&#xff0c;为用户提供了更便捷的自动续期和管理解决方案。 什…

5G的SUCI、SUPI、5G-GUTI使用场景及关系

使用场景(来源于对23.501、23.502、33.501、23.003的理解) 1、UE初始注册时&#xff0c;根据HN Public Key把SUPI加密成SUCI&#xff0c;并发送初始注册请求 2、AMF转发SUCI给AUSF和UDM进行认证&#xff0c;并获取解密后的SUPI 3、AMF根据SUPI生成一个5G-GUTI&#xff0c;并保…

大数据-226 离线数仓 - Flume 优化配置 自定义拦截器 拦截原理 拦截器实现 Java

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; Java篇开始了&#xff01; 目前开始更新 MyBatis&#xff0c;一起深入浅出&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff0…

PyAEDT:Ansys Electronics Desktop API 简介

在本文中&#xff0c;我将向您介绍 PyAEDT&#xff0c;这是一个 Python 库&#xff0c;旨在增强您对 Ansys Electronics Desktop 或 AEDT 的体验。PyAEDT 通过直接与 AEDT API 交互来简化脚本编写&#xff0c;从而允许在 Ansys 的电磁、热和机械求解器套件之间无缝集成。通过利…

定时器(QTimer)与随机数生成器(QRandomGenerator)的应用实践——Qt(C++)

一、QTimer与QRandomGenerator &#xff08;一&#xff09;QTimer&#xff08;定时器&#xff09;[2] QTimer类为定时功能提供了一个高级编程接口。在使用QTimer时&#xff0c;实例化一个QTimer对象并将其timeout()发射信号与合适的信号槽相连接。通过调用QTimer的start()函数…

用redis的zset实现日榜,周榜,月榜

思路&#xff1a; 1.初始化一个月的数据&#xff1a; /*** 初始化一个月数据*/Testpublic void initMonthData(){//计算当前时间小时的keylong hourSystem.currentTimeMillis()/(1000*60*60);for(int i1;i<24*30;i){String key"W_hour"(hour-i);Random random new…

通过shell脚本分析部署nginx网络服务

通过shell脚本分析部署nginx网络服务 1.接收用户部署的服务名称 [rootlocalhost xzy]# vim 1.sh [rootlocalhost xzy]# chmod x 1.sh [rootlocalhost xzy]# ./1.sh2.判断服务是否安装 已安装&#xff1b;自定义网站配置路径为/www&#xff1b;并创建共享目录和网页文件&…

威胁驱动的网络安全方法论

摘要 目前的网络安全风险管理实践很大程度上是由合规性要求驱动的&#xff0c;这使得公司/组织不得不在安全控制和漏洞上投入人力/物力。&#xff08;风险管理涉及多个方面&#xff0c;包括资产、威胁、漏洞和控制&#xff0c;并根据事故发生的可能性及造成的影响进行评估。威…

『VUE』30. 生命周期的介绍(详细图文注释)

目录 生命周期生命周期的8阶段生命周期小例子总结 欢迎关注 『VUE』 专栏&#xff0c;持续更新中 欢迎关注 『VUE』 专栏&#xff0c;持续更新中 生命周期 每个 Vue 组件实例在创建时都需要经历一系列的初始化步骤&#xff0c;比如设置好数据侦听&#xff0c;编译模板&#xf…

idea 通过git撤销commit但未push的操作

1、undo commit 适用情况&#xff1a;代码修改完了&#xff0c;已经Commit了&#xff0c;但是还未push&#xff0c;然后发现还有地方需要修改不想提交本次记录了。这时可以进行Undo Commit&#xff0c;修改后再重新Commit。注意&#xff1a;如果已经进行了Push&#xff0c;线上…

【graphics】图形绘制 C++

众所周知&#xff0c;周知所众&#xff0c;图形绘制对于竞赛学僧毫无用处&#xff0c;所以这个文章&#xff0c;专门对相关人员教学&#xff08;成长中的码农、高中僧、大学僧&#xff09;。 他人经验教学参考https://blog.csdn.net/qq_46107892/article/details/133386358?o…

Spring Boot出现java: 错误: 无效的源发行版:16的解决方式

第一步&#xff1a; 修改为SDK的目标字节码版本 第二步&#xff1a;CtrlShiftAltS进入项目结构 第三步&#xff1a;pom.xml文件中 在网上搜索和自己SDK适配的Springboot版本&#xff0c;1.8对应的是2.7.1&#xff08;可以用&#xff09; 修改Java版本为1.8 最后的最后&a…

FPGA 第6讲 简单组合逻辑多路选择器

时间&#xff1a;2024.11.11-11.14 一、学习内容 1.组合逻辑 组合逻辑是VerilgHDL设计中一个重要组成部分。从电路本质上讲&#xff0c;组合逻辑电路的特点是输出信号只是当前时刻输入信号的函数&#xff0c;与其他时刻的输入状态无关&#xff0c;无存储电路&#xff0c;也没…

【C++初阶】C++入门

1、C第一个程序 C是脱胎于C语言的&#xff0c;所以也包含了C语言绝大多数的内容&#xff0c;C兼容C语言绝大多数的语法,在C语言中能实现的程序在C中也是可以执行的&#xff0c;但需要将定义文件代码的后缀改为.cpp 就比如hello world程序 // test.cpp #include<stdio.h&g…

selenium元素定位校验以及遇到的元素操作问题记录

页面元素定位方法及校验 使用比较多的是通过id、class和xpath来对元素进行定位。在定位前可以现在浏览器验证是否可以找到指定的元素。这样就不用每添加一个元素定位都运行代码来检查定位方式表达式是否正确。 使用XPATH定位 在浏览器F12&#xff0c;找到元素&#xff0c;在元…

网络安全之国际主流网络安全架构模型

目前&#xff0c;国际主流的网络安全架构模型主要有&#xff1a; ● 信息技术咨询公司Gartner的ASA&#xff08;Adaptive Security Architecture自适应安全架构&#xff09; ● 美国政府资助的非营利研究机构MITRE的ATT&CK&#xff08;Adversarial Tactics Techniques &…