排序算法 -归并排序

文章目录

  • 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

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

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

相关文章

wireshark 基础

wireshark 基础 一、wireshark介绍 Wireshark&#xff08;前称Ethereal&#xff09;是一个网络封包分析软件。网络封包分析软件的功能是捕获网络封包&#xff0c;并尽可能显示出最为详细的网络封包资料。Wireshark使用WinPCAP作为接口&#xff0c;直接与网卡进行数据报文交换…

GIT 入门详解指南

前言&#xff1a; 注&#xff1a;本博客仅用于记录本人学习过程中对git的理解&#xff0c;仅供学习参考&#xff0c;如有异议请自行查资料求证 安装 使用git之前必须完成git的安装&#xff0c;Git 目前支持 Linux/Unix、Solaris、Mac和 Windows 平台上运行 git 安装教程 基本…

从 IDC 到云原生:稳定性提升 100%,成本下降 50%,热联集团的数字化转型与未来展望

作者&#xff1a;金峰&#xff08;项良&#xff09;、朱永林、赵世振&#xff08;寰奕&#xff09; 公司简介 杭州热联集团股份有限公司成立于 1997 年 10 月&#xff0c;是隶属杭州市实业投资集团的国有控股公司。公司专业从事国际、国内钢铁贸易黑色大宗商品及产业服务&…

【微软:多模态基础模型】(4)统一视觉模型

欢迎关注[【youcans的AGI学习笔记】](https://blog.csdn.net/youcans/category_12244543.html&#xff09;原创作品 【微软&#xff1a;多模态基础模型】&#xff08;1&#xff09;从专家到通用助手 【微软&#xff1a;多模态基础模型】&#xff08;2&#xff09;视觉理解 【微…

机器学习——期末复习 重点题归纳

第一题 问题描述 现有如下数据样本&#xff1a; 编号色泽敲声甜度好瓜1乌黑浊响高是2浅白沉闷低否3青绿清脆中是4浅白浊响低否 &#xff08;1&#xff09;根据上表&#xff0c;给出属于对应假设空间的3个不同假设。若某种算法的归纳偏好为“适应情形尽可能少”&#xff0c;…

Web3浪潮下的区块链应用:从理论到实践的全面解析

随着Web3的兴起&#xff0c;区块链技术作为其核心支撑&#xff0c;正迎来前所未有的应用爆发。Web3不仅仅是技术的革新&#xff0c;更代表了一种去中心化、开放、透明的互联网愿景。在这一背景下&#xff0c;区块链技术的应用正从理论走向实践&#xff0c;推动着各行各业的数字…

学习大数据DAY61 宽表加工

目录 模型设计 加工宽表 任务调度&#xff1a; 大表 - 把很多数据整合起来 方便后续的明细查询和指标计算 模型设计 设计 建模 设计: excel 文档去编写 建模: 使用建模工具 PowerDesigner Navicat 在线画图工具... 把表结构给绘 制出来 共享\项目课工具\pd 加工宽表 数…

ChromeDriver驱动下载地址更新(保持最新最全)

说明&#xff1a; ChromeDriver 是 Selenium WebDriver 用于控制 Chrome 的独立可执行文件。 为了方便下载使用&#xff0c;本文保持ChromeDriver的最新版本更新&#xff0c;并提供115.0.5763.0-133.0.6841.0版本的下载地址&#xff1a; 所有版本和下载地址&#xff1a; &am…

QT基本绘图

QT绘图 1.概述 这篇文章介绍如何绘图 2.绘图基本操作 创建一个普通的widget类型的项目 在widget.h 文件中重写绘图事件 #ifndef WIDGET_H #define WIDGET_H#include <QWidget>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : p…

[ACTF2020]Upload 1--详细解析

信息收集 题目告诉我们是一道upload&#xff0c;也就是文件上传漏洞题目。 进入界面&#xff0c;是一个灯泡&#xff0c;将鼠标放在图标上就会出现文件上传的相应位置&#xff1a; 思路 文件上传漏洞&#xff0c;先看看有没有前端校验。 在js源码中找到了前端校验&#xff…

Android Studio开发学习(五)———LinearLayout(线性布局)

一、布局 认识了解一下Android中的布局&#xff0c;分别是: LinearLayout(线性布局)&#xff0c;RelativeLayout(相对布局)&#xff0c;TableLayout(表格布局)&#xff0c; FrameLayout(帧布局)&#xff0c;AbsoluteLayout(绝对布局)&#xff0c;GridLayout(网格布局) 等。 二、…

计算机视觉在自动驾驶汽车中的应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 计算机视觉在自动驾驶汽车中的应用 计算机视觉在自动驾驶汽车中的应用 计算机视觉在自动驾驶汽车中的应用 引言 计算机视觉在自动…

表格的选择弹窗,选中后返显到表格中

项目场景&#xff1a; 提示&#xff1a;这里简述项目相关背景&#xff1a; 表格的下拉框可以直接显示选项&#xff0c;那如果选择框不是下拉的&#xff0c;而是弹窗&#xff0c;那么在表格中如何返显呢&#xff1f; 问题描述 如上图所示&#xff0c;点击表格中的选择&#xf…

金融领域先锋!海云安成功入选2024年人工智能先锋案例集

近日&#xff0c;中国人工智能产业发展联盟《2024年人工智能先锋案例集》&#xff08;以下简称“AIIA先锋案例集”&#xff09;在中国人工智能产业发展联盟第十三次全体会议上正式发布。该案例集由人工智能产业发展联盟&#xff08;AIIA&#xff09;、工业和信息化部新闻宣传中…

HarmonyOs鸿蒙开发实战(16)=>沉浸式效果第一种方案一窗口全屏布局方案

1.沉浸式效果的目的 开发应用沉浸式效果主要指通过调整状态栏、应用界面和导航条的显示效果来减少状态栏导航条等系统界面的突兀感&#xff0c;从而使用户获得最佳的UI体验。 2.窗口全屏布局方案介绍 调整布局系统为全屏布局&#xff0c;界面元素延伸到状态栏和导航条区域实现沉…

OpenAI震撼发布:桌面版ChatGPT,Windows macOS双平台AI编程体验!

【雪球导读】 「OpenAI推出ChatGPT桌面端」 OpenAI重磅推出ChatGPT桌面端&#xff0c;全面支持Windows和macOS系统&#xff01;这款新工具为用户在日常生活和工作中提供了前所未有的无缝交互体验。对于那些依赖桌面端进行开发工作的专业人士来说&#xff0c;这一更新带来了令人…

Android OpenGLES2.0开发(八):Camera预览

严以律己&#xff0c;宽以待人 引言 终于到该章节了&#xff0c;还记得Android OpenGLES2.0开发&#xff08;一&#xff09;&#xff1a;艰难的开始章节说的吗&#xff1f;写这个系列的初衷就是因为每次用到GLSurfaceViewCamera预览时&#xff0c;总是CtrlC、CtrlV从来没有研究…

独立站干货:WordPress主机推荐

WordPress作为全球最受欢迎的独立站建设平台&#xff0c;提供了灵活性和强大的功能&#xff0c;使得建站变得简单而高效。本文将为您详细介绍WordPress建站的流程&#xff0c;并推荐几款实测后觉得好用的主机商。 WordPress建站流程 域名注册 首先需要注册一个域名&#xff0c…

细说STM32单片机DMA中断收发RTC实时时间并改善其鲁棒性的方法

目录 一、DMA基础知识 1、DMA简介 (1)DMA控制器 (2)DMA流 (3)DMA请求 (4)仲裁器 (5)DMA传输属性 2、源地址和目标地址 3、DMA传输模式 4、传输数据量的大小 5、数据宽度 6、地址指针递增 7、DMA工作模式 8、DMA流的优先级别 9、FIFO或直接模式 10、单次传输或突…

基于Spring Boot+Vue的多媒体素材管理系统的设计与实现

一.系统开发工具与环境搭建 1.系统设计开发工具 后端使用Java编程语言的Spring boot框架 项目架构&#xff1a;B/S架构 运行环境&#xff1a;win10/win11、jdk17 前端&#xff1a; 技术&#xff1a;框架Vue.js&#xff1b;UI库&#xff1a;ElementUI&#xff1b; 开发工具&…