当前位置: 首页 > article >正文

排序算法 -归并排序

文章目录

  • 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.kler.cn/a/395556.html

相关文章:

  • Python sys模块介绍
  • 使用 Prompt API 与您的对象聊天
  • 【WPF】Prism学习(二)
  • 【LeetCode】每日一题 2024_11_14 统计好节点的数目(图/树的 DFS)
  • Ceph 中PG与PGP的概述
  • 使用Python实现对接Hadoop集群(通过Hive)并提供API接口
  • 机器学习的常用算法
  • SQLite3 JDBC Java工具类
  • 网站部署到IIS后,数据库登录失败
  • 一百多块可以买到什么样的开放式耳机?虹觅Olite评测推荐
  • 机器学习—诊断偏差和方差
  • 两路组相联缓存配置
  • 【Rust调用Windows API】获取正在运行的全部进程信息
  • C++的起源与发展
  • java:接口,抽象,多态的综合小练习
  • Prompt设计技巧和高级PE
  • 微服务day07
  • 2024年9月青少年软件编程(C语言/C++)等级考试试卷(五级)
  • 基于卷积神经网络的农作物病虫害识别与防治系统,vgg16,resnet,swintransformer,模型融合(pytorch框架,python代码)
  • 什么是 C++ 中的常量表达式? 有什么用途?如何判断一个表达式是否是常量表达式?
  • Redis的分布式锁分析
  • 【人工智能】Transformers之Pipeline(二十三):文档视觉问答(document-question-answering)
  • 【MySQL 保姆级教学】详细讲解视图--(15)
  • 五、函数封装及调用、参数及返回值、作用域、匿名函数、立即执行函数
  • 利用OpenAI进行测试需求分析——从电商网站需求到测试用例的生成
  • 移动端异构运算技术 - GPU OpenCL 编程(基础篇)