归并排序算法

归并排序

1算法介绍

和选择排序一样,归并排序的性能不受输入数据的影响,但表现比选择排序好的多,因为始终都是O(n log n)的时间复杂度。代价是需要额外的内存空间。归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法的一个非常典型的应用。

2基本思想

基本思路就是将数组分成二组 A,B,如果这二组组内的数据都是有序的,那么就可以 很方便的将这二组数据进行排序。如何让这二组组内数据有序了?

可以将 A,B 组各自再分成二组。依次类推,当分出来的小组只有一个数据时,可以认为这个小组组内已经达到了有序,然后再合并相邻的二个小组就可以了。这样通过先递归的分解数列,再合并数列就完成了归并排序。

c 复制代码
#include <stdio.h>

void find(int arr[], int left, int mid, int right)
{
    int i, j, k;             // 定义索引变量
    int n1 = mid - left + 1; // 计算左边子数组的长度
    int n2 = right - mid;    // 计算右边子数组的长度
    int L[n1], R[n2];        // 创建左右两个临时数组
    for (i = 0; i < n1; i++)
    {
        L[i] = arr[left + i]; // 将左子数组元素复制到L中
    }
    for (j = 0; j < n2; j++)
    {
        R[j] = arr[mid + 1 + j]; // 将右子数组元素复制到R中
    }
    i = 0;    // 初始化左子数组索引
    j = 0;    // 初始化右子数组索引
    k = left; // 初始化合并后数组的起始位置
    while (i < n1 && j < n2)
    {
        if (L[i] <= R[j])  // 当左右子数组都未完全遍历时,进行合并操作
        {                  // 如果左子数组的当前元素小于等于右子数组的当前元素
            arr[k] = L[i]; // 将左子数组的元素放入合并后的数组
            i++;           // 移动左子数组的索引
        }
        else
        {
            arr[k] = R[j]; // 将右子数组的元素放入合并后的数组
            j++;           // 移动右子数组的索引
        }
        k++; // 移动合并后数组的索引
    }
    while (i < n1)
    {                  // 如果左子数组还有剩余元素
        arr[k] = L[i]; // 将左子数组的剩余元素放入合并后的数组
        i++;           // 移动左子数组的索引
        k++;           // 移动合并后数组的索引
    }
    while (j < n2)
    {                  // 如果右子数组还有剩余元素
        arr[k] = R[j]; // 将右子数组的剩余元素放入合并后的数组
        j++;           // 移动右子数组的索引
        k++;           // 移动合并后数组的索引
    }
    return;
}
void merge(int arr[], int left, int right)
{
    if (left < right)
    {                                        // 如果左边界小于右边界,说明还有多个元素需要排序
        int mid = left + (right - left) / 2; // 计算中点,避免溢出
        merge(arr, left, mid);               // 对左子数组进行归并排序
        merge(arr, mid + 1, right);          // 对右子数组进行归并排序
        find(arr, left, mid, right);         // 合并两个已排序的子数组
    }
    return;
}

int main()
{
    int arr[] = {38, 27, 43, 3, 9, 82, 10};
    int n = sizeof(arr) / sizeof(arr[0]);
    merge(arr, 0, n - 1); // 调用归并排序函数,对数组进行排序
    printf("排序后为: \n");
    for (int i = 0; i < n; i++)
    {
        printf("%d ", arr[i]);
    }
    printf("\n");
    return 0;
}
相关推荐
Jerry2 小时前
LeetCode 101. 对称二叉树
算法
可编程芯片开发3 小时前
基于MPPT最大功率跟踪的离网光伏发电系统Simulink建模与仿真
算法
AI科技星3 小时前
线性算子不是空间映射函数,是全域双螺旋场之间拉伸、旋转、耦合、坍缩的跨空间标准化变换载体《全域数学vs传统数学:人类文明进阶200讲》第80讲
线性代数·算法·矩阵·数据挖掘·回归·乖乖数学·全域数学
米罗篮3 小时前
矩阵快速幂 (Exponentiation By Squaring Applied To Matrices)
c++·线性代数·算法·矩阵
dream_home84073 小时前
图像算法模型NPU适配与算法服务实战指南
人工智能·python·算法·npu 图像服务
大鱼>4 小时前
多宠物家庭智能管理平台:云端架构与多设备协同实战
python·算法·iot·宠物
To_OC5 小时前
LC 22 括号生成:刷完这道题,我终于搞懂回溯剪枝了
javascript·算法·leetcode
To_OC5 小时前
LC 39 组合总和:回溯入门必刷题,我踩过的两个坑都在这了
javascript·算法·leetcode
数字杂技师5 小时前
每条推荐都很准,为什么我还是越刷越无聊?
算法
兰令水5 小时前
hot100【acm版】【2026.7.14打卡-java版本】
java·数据结构·算法·leetcode·面试