归并排序 python C C++ 代码及解析

news2024/11/26 23:29:26

一,概念及其介绍

归并排序(Merge sort)是建立在归并操作上的一种有效、稳定的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;若将两个有序表合并成一个有序表,称为二路归并

二,复杂度说明

时间复杂度: O(nlogn)

对于自顶向下的归并排序, 归并排序通过不断将数组对半划分,直到每个子数组只有一个元素(这需要 logn次划分)。然后,合并这些子数组的过程中,每个元素都需要被处理一次,总共需要处理 n个元素。所以总的操作次数约为 nlog n ,因此时间复杂度为 O(nlog n)

空间复杂度:  O(n)

空间复杂度为 O(n) 是因为在合并子数组的过程中,需要额外创建一个与原数组大小相同的辅助数组来存放合并后的结果。所以空间复杂度主要取决于这个辅助数组的大小,即为 O(n)。

三,过程图示

归并排序是递归算法的一个实例,这个算法中基本的操作是合并两个已排序的数组,取两个输入数组 A 和 B,一个输出数组 C,以及三个计数器 i、j、k,它们初始位置置于对应数组的开始端。

A[i] 和 B[j] 中较小者拷贝到 C 中的下一个位置,相关计数器向前推进一步。

当两个输入数组有一个用完时候,则将另外一个数组中剩余部分拷贝到 C 中

四.代码及解析

4.1 python 

思路:

使用两个函数完成,一个函数用于连接两个有序列表,返回一个有序的新列表,一个函数用于递归将已知列表分为左右两部分,递归分割,再进行连接,当列表中只有一个元素时则一定是有序的

知识点:

1.列表的append用于向列表添加一个元素

2.列表的extend用于向列表添加一个可迭代对象

# merge_sort的主要作用是通过递归地将输入的数组不断地分割成更小的子数组,
# 直到子数组的长度为 1 (此时子数组本身就是有序的),然后调用 merge 函数将这些有序的子数组合并起来,
# 最终实现对整个数组的排序
def merge_sort(arr):
    if len(arr) <= 1:
        return arr
    mid = len(arr) // 2
    left_half = merge_sort(arr[:mid])
    right_half = merge_sort(arr[mid:])
    return merge(left_half, right_half)

# arr = [12, 11, 13, 5, 6]
# merge函数用于连接两个有序数列。并存放到新数列中
def merge(left, right):
    merged = []
    left_index = 0
    right_index = 0
    # 两两对比,小的放入新列表,所在列表的下标指向往后移动,大的所在列表下标指向不变
    while left_index < len(left) and right_index < len(right):
        if left[left_index] < right[right_index]:
            merged.append(left[left_index])
            left_index += 1
        else:
            merged.append(right[right_index])
            right_index += 1
    # 利用切片将剩下的元素放到新列表中
    merged.extend(left[left_index:])
    merged.extend(right[right_index:])
    return merged

# 测试示例
arr = [12, 11, 13, 5, 6]
sorted_arr = merge_sort(arr)
print("排序后的数组:", sorted_arr)
排序后的数组: [5, 6, 11, 12, 13]

4.2 C

思路:

使用两个函数,一个函数用于递归将数组左右两部分割开,再递归分割,直到分割到只有一个元素时一定是有序的,再进行两个有序数组的连接,这里再定义另一个函数作用是连接两个有序数组

注意点:

1.直接传入数组进行操作,所以两个函数都不需要返回值

2.merge函数利用两个新的数组,分别存放左右两边的原数组,再进行比较,依次放入原数组

3.int m = l + (r - l) / 2; 这个表达式中使用 r - l 是为了计算数组区间 [l, r] 的长度。

通过 (r - l) 得到区间的长度后再除以 2,就能得到区间长度的一半。然后加上起始索引 l ,就可以得到区间的中间位置 m ,从而将数组划分为左右两个子区间 [l, m] 和 [m + 1, r] ,以便进行归并排序的递归操作

#include <stdio.h>

// 合并两个已排序的子数组为一个排序数组
void merge(int arr[], int l, int m, int r) {
    int n1 = m - l + 1; // 左边子数组的大小
    int n2 = r - m;     // 右边子数组的大小

    // 创建临时数组
    int L[n1], R[n2];

    // 复制数据到临时数组
    for (int i = 0; i < n1; i++)
        L[i] = arr[l + i];
    for (int j = 0; j < n2; j++)
        R[j] = arr[m + 1 + j];

    int i = 0, j = 0, k = l;

    // 合并临时数组回到原始数组
    while (i < n1 && j < n2) {
        if (L[i] <= R[j]) {
            arr[k++] = L[i++];
        } else {
            arr[k++] = R[j++];
        }
    }

    // 复制剩余的元素
    while (i < n1) {
        arr[k++] = L[i++];
    }

    while (j < n2) {
        arr[k++] = R[j++];
    }
}

// 归并排序函数
void mergeSort(int arr[], int l, int r) {
    if (l < r) {
        int m = l + (r - l) / 2; // 取中间元素作为分割点

        // 对左边的子数组进行排序
        mergeSort(arr, l, m);

        // 对右边的子数组进行排序
        mergeSort(arr, m + 1, r);

        // 合并两个已排序的子数组
        merge(arr, l, m, r);
    }
}

// 打印数组函数
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};
    int arr_size = sizeof(arr) / sizeof(arr[0]);

    printf("before sort: \n");
    printArray(arr, arr_size);

    mergeSort(arr, 0, arr_size - 1);

    printf("after sort: \n");
    printArray(arr, arr_size);

    return 0;
}
before sort:
12 11 13 5 6
after sort:
5 6 11 12 13

4.3 C++

与C语言思路一致,只有一些语法上的小差别

#include <iostream>

// 合并两个已排序的子数组为一个排序数组
void merge(int arr[], int l, int m, int r) {
    int n1 = m - l + 1;
    int n2 = r - m;

    int L[n1], R[n2];

    for (int i = 0; i < n1; i++)
        L[i] = arr[l + i];
    for (int j = 0; j < n2; j++)
        R[j] = arr[m + 1 + j];

    int i = 0, j = 0, k = l;

    while (i < n1 && j < n2) {
        if (L[i] <= R[j]) {
            arr[k++] = L[i++];
        } else {
            arr[k++] = R[j++];
        }
    }

    while (i < n1) {
        arr[k++] = L[i++];
    }

    while (j < n2) {
        arr[k++] = R[j++];
    }
}

// 归并排序函数
void mergeSort(int arr[], int l, int r) {
    if (l < r) {
        int m = l + (r - l) / 2;
        mergeSort(arr, l, m);
        mergeSort(arr, m + 1, r);
        merge(arr, l, m, r);
    }
}

// 打印数组函数
void printArray(int arr[], int size) {
    for (int i = 0; i < size; i++)
        std::cout << arr[i] << " ";
    std::cout << std::endl;
}

// 测试案例
int main() {
    int arr[] = {12, 11, 13, 5, 6};
    int arr_size = sizeof(arr) / sizeof(arr[0]);

    std::cout << "排序前的数组为: ";
    printArray(arr, arr_size);

    mergeSort(arr, 0, arr_size - 1);

    std::cout << "排序后的数组为: ";
    printArray(arr, arr_size);

    return 0;
}
排序前的数组为: 12 11 13 5 6 
排序后的数组为: 5 6 11 12 13 

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

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

相关文章

商家转账到零钱开通最快捷径

商家转账到零钱存在一定的捷径&#xff0c;这一捷径将放在文章最后。如果商家希望自行开通&#xff0c;可以按照以下步骤进行申请&#xff1a; 1. 确认主体资格&#xff1a;申请主体必须是公司性质&#xff08;有限公司类型&#xff09;&#xff0c;个体工商户暂不支持申请&…

企业级Linux系统防护

一、企业级Linux系统防护概述 一&#xff09;企业级Linux系统安全威胁 企业级Linux系统安全威胁列表 解决的主要安全威胁安全威胁牵涉到的人员及操作文件系统防护避免有意/无意的文件篡改、越权访问&#xff0c;根用户&#xff08;root&#xff09;权限泛滥企业内部用户误操作、…

【Golang 面试 - 基础题】每日 5 题(九)

✍个人博客&#xff1a;Pandaconda-CSDN博客 &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/UWz06 &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 Golang 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;收藏…

Linux虚拟化技术KVM

文章目录 虚拟化基础什么是虚拟化虚拟化优势虚拟机虚拟机的主要特征Hypervisor类型类型1&#xff1a;裸金属型类型2&#xff1a;宿主型 KVM概述KVM体系结构KVM模块载入后的系统运行模式KVM集中管理和控制宿主机环境准备 安装KVM工具包libvirt包功能libvirt结构图安装KVM相关包C…

SEO优化 prerender-spa-plugin工具使用 踩坑记录

安装prerender-spa-plugin yarn add prerender-spa-plugin 或 npm install prerender-spa-plugin初始配置 后面记录踩的坑 配置路由 const routes [{path: /,redirect: {path: /HomeView},},{path: /home,redirect: {path: /HomeView},},{ path: /HomeView,component: HomeV…

postgresql密码复杂度验证和有效期

前言 为了数据库安全以及应对等保测评等要求&#xff0c;我们需要设置密码复杂度。我们通过passwordcheck模块实现复杂度检测功能。 启用密码复杂度验证 找到自己安装pg库的配置文件目录&#xff0c;修改postgresql.conf vim postgresql.conf修改如下内容 shared_preload_…

2023版IDEA安装通义灵码屡遭挫败:重复尝试,安装依旧失败

目录 背景: 过程: 第一步: 第二步: 第三步: 安装成功: 总结: 通义灵码的优点: 背景: 小编使用的是2023版本IDEA&#xff0c;在安装通义灵码的时候出现了一件很让人头痛的问题&#xff0c;我在IEDA中的插件中心里面去下载&#xff0c;但是当我我安装的进度条加载完成之…

命令行创建git仓库

方法1&#xff1a;初始化自己的仓库 git init创建完成之后可以用ls -a查看是否存在.git文件 如果不想要git仓库&#xff0c;可以使用rm -rf .git删除仓库 方法2&#xff1a;克隆别人的仓库 git clone [http][http]是仓库网址 总体流程 可以看到文件分为四种状态&#xff0c…

windows无法打开添加打印机原因分析及解决方法

在日常办公和生活中&#xff0c;打印机是不可或缺的重要设备。然而&#xff0c;有时在添加打印机的过程中&#xff0c;经常会遇各种问题。今天有个小伙伴问我windows无法打开添加打印机怎么回事&#xff1f;今天就教大家windows无法打开添加打印机原因分析及解决方法。 添加打打…

氧传感器在码头油气回收船岸安全装置中的重要作用

随着全球对环境保护和安全生产要求的日益提升&#xff0c;石化码头的油气回收问题已成为行业关注的焦点。在汽油、航煤、苯、对二甲苯等油品和化学品的装船过程中&#xff0c;大量油气挥发不仅加剧了大气污染&#xff0c;还潜藏着对人体健康的严重威胁。因此&#xff0c;推广和…

芋道以开源之名行下作之事 恬不知耻 标榜自己开源 公开源码+sql 不用再加入知识星球

资源 链接: https://pan.baidu.com/s/1TeuxbAUfLQ5_BqMBF1kniQ?pwdcqud 提 取码: cqud 依次为后端、补充版的sql、前端 此文档内安装部署等一应俱全

天气预报的爬虫内容打印并存储用户操作

系统名称&#xff1a; 基于网络爬虫技术的天气数据查询系统文档作者&#xff1a;清馨创作时间&#xff1a;2024-7-29最新修改时间&#xff1a;2024-7-29最新版本号&#xff1a; 1.0 1.背景描述 该系统将基于目前比较流行的网络爬虫技术&#xff0c;对网站上&#xff08;NowAPI…

数据结构之八大排序(上)

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a;数据结构&#xff08;Java版&#xff09; 目录 排序的相关介绍 直接插入排序 希尔排序&#xff08;缩小增量排序&#xff09; 选择排序 …

Datawhale AI夏令营 AI+逻辑推理 Task2总结

Datawhale AI夏令营 AI逻辑推理 Task2总结 一、大语言模型解题方案介绍 1.1 大模型推理介绍 ​ 推理是建立在训练完成的基础上&#xff0c;将训练好的模型应用于新的、未见过的数据&#xff0c;模型利用先前学到的规律进行预测、分类和生成新内容&#xff0c;使得AI在实际应…

【Linux】3.Linux 指令大揭秘:常见八个指令的妙用(下)

欢迎来到 CILMY23 的博客 &#x1f3c6;本篇主题为&#xff1a;Linux 指令大揭秘&#xff1a;常见八个指令的妙用&#xff08;下&#xff09; &#x1f3c6;个人主页&#xff1a;CILMY23-CSDN博客 &#x1f3c6;系列专栏&#xff1a;Python | C | C语言 | 数据结构与算法 | …

华为机试HJ76尼科彻斯定理

华为机试HJ76尼科彻斯定理 题目&#xff1a; 想法&#xff1a; 从题目可以找到规律&#xff0c;输出的第一个奇数为 ( 当前输入数值 − 1 ) 当前输入数值 1 (当前输入数值-1)当前输入数值1 (当前输入数值−1)当前输入数值1&#xff0c;输出是连续的输入数值个数个奇数&#…

资金管理平台 -SAP创建凭证测试程序及增强!

文章目录 主要程序创建程序程序 代码解析变量定义抬头和项目初始值表头赋值调用BAPI其他的子例程 核心内表增强部分LFACIF5D程序FI_DOCUMENT_CHECK完整程序 BADI增强 主要程序 创建程序 程序 &---------------------------------------------------------------------* *…

2.Redis安装

1.安装需要的依赖 因为是c语言编写的&#xff0c;所以需要gcc依赖。 yum install -y gcc tcl 这一步可能会遇到的问题解决方案参照博文地址&#xff1a; yum 报错&#xff1a;Could not retrieve mirrorlist http://mirrorlist.centos.org_yum install could not retrieve mi…

花几千上万学习Java,真没必要!(三十五)

1、Map&#xff1a; Map接口的基本且常用的操作&#xff0c;用于管理键值对集合。 V put(K key, V value) 作用&#xff1a;向映射中添加一个键值对。 参数&#xff1a;K key 是键的类型&#xff0c;V value 是与键关联的值。 返回值&#xff1a;如果映射以前包含该键的映射关…

upload-labs靶场(1-19关)

upload-labs靶场 简介 upload-labs是一个使用php语言编写的&#xff0c;专门收集渗透测试过程中遇到的各种上传漏洞的靶场。旨在帮助大家对上传漏洞有一个全面的了解。目前一共19关&#xff0c;每一关都包含着不同上传方式。 注意&#xff1a;能运行<?php phpinfo();?&…