C语言---排序算法5---迭代归并排序法

文章目录

归并排序(Merge Sort)是一种基于分治思想的排序算法,其迭代实现(自底向上)通过逐步合并有序子数组来完成排序,避免了递归调用的开销。

算法原理

1、分阶段:将数组视为由多个长度为1的子数组组成(初始时每个元素自成一个有序子数组)。

2、合阶段:逐步合并相邻的子数组,每次合并后子数组长度翻倍(1→2→4→...),直到整个数组有序。

迭代法步骤

1、初始化:设置子数组的初始长度 size = 1。

2、循环合并:

将数组分成多个长度为 size 的子数组。

合并相邻的两个子数组(每个子数组内部已有序),生成一个长度为 2size 的有序子数组。
如果剩余元素不足 2
size,直接合并剩余部分。

3、更新长度:size *= 2,重复合并直到 size >= n(数组长度)。

代码实现

代码实现1:

bash 复制代码
#include <stdio.h>
#include <stdlib.h>

// 合并两个有序子数组 arr[left..mid] 和 arr[mid+1..right]
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));

    // 拷贝数据到临时数组
    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];

    // 合并临时数组回原数组
    int i = 0, j = 0, k = left;
    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++];

    free(L);
    free(R);
}

// 迭代法归并排序
void mergeSortIterative(int arr[], int n) {
    int size = 1; // 初始子数组长度为1
    while (size < n) {
        int left = 0;
        while (left < n - 1) {
            int mid = left + size - 1;
            if (mid >= n - 1) mid = n - 1; // 防止越界
            int right = (left + 2 * size - 1) < (n - 1) ? (left + 2 * size - 1) : (n - 1);
            merge(arr, left, mid, right);
            left += 2 * size; // 移动到下一对子数组的起始位置
        }
        size *= 2; // 子数组长度翻倍
    }
}

// 测试代码
int main() {
    int arr[] = {12, 11, 13, 5, 6, 7};
    int n = sizeof(arr) / sizeof(arr[0]);

    printf("原始数组: ");
    for (int i = 0; i < n; i++) printf("%d ", arr[i]);
    printf("\n");

    mergeSortIterative(arr, n);

    printf("排序后数组: ");
    for (int i = 0; i < n; i++) printf("%d ", arr[i]);
    printf("\n");

    return 0;
}

代码实现2(摘抄自菜鸟教程):

c 复制代码
#include <stdio.h>
#include <stdlib.h>
 
// 函数声明
int min(int x, int y);
void merge_sort(int arr[], int len);
 
int main() {
    int arr[] = { 22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70 };
    int len = sizeof(arr) / sizeof(arr[0]);  // 计算数组长度
 
    merge_sort(arr, len);  // 调用归并排序函数
 
    // 打印排序后的数组
    for (int i = 0; i < len; i++) {
        printf("%d ", arr[i]);
    }
 
    return 0;
}
 
// 返回两个数中的最小值
int min(int x, int y) {
    return x < y ? x : y;
}
 
// 归并排序函数
void merge_sort(int arr[], int len) {
    int* a = arr;
    int* b = (int*) malloc(len * sizeof(int));
 
    if (b == NULL) {  // 检查内存分配是否成功
        fprintf(stderr, "Memory allocation failed\n");
        exit(EXIT_FAILURE);
    }
 
    for (int seg = 1; seg < len; seg += seg) {
        for (int start = 0; start < len; start += seg + seg) {
            int low = start;
            int mid = min(start + seg, len);
            int high = min(start + seg + seg, len);
            int k = low;
            int start1 = low, end1 = mid;
            int start2 = mid, end2 = high;
 
            // 合并两个子数组
            while (start1 < end1 && start2 < end2) {
                b[k++] = a[start1] < a[start2] ? a[start1++] : a[start2++];
            }
            while (start1 < end1) {
                b[k++] = a[start1++];
            }
            while (start2 < end2) {
                b[k++] = a[start2++];
            }
        }
 
        // 交换数组指针
        int* temp = a;
        a = b;
        b = temp;
    }
 
    // 如果a和arr不相同,则将a的内容复制回arr
    if (a != arr) {
        for (int i = 0; i < len; i++) {
            b[i] = a[i];
        }
        b = a;
    }
 
    free(b);  // 释放内存
}

迭代法 vs 递归法

特性 迭代法 递归法
实现方式 通过循环逐步合并子数组 通过递归分解问题
空间开销 仅需临时数组空间 递归栈空间(可能栈溢出)
代码复杂度 稍复杂(需手动管理边界) 更简洁(分治逻辑直观)

优化方向

1、小数组优化:当子数组长度较小时(如 size <= 16),改用插入排序以减少常数因子。

2、原地归并:通过复杂指针操作减少临时空间使用(但实现难度高,可能牺牲稳定性)。

学习视频推荐

数据结构合集 - 归并排序(非递归与递归算法过程, 效率分析, 稳定性分析)

相关推荐
拼好饭和她皆失2 小时前
数学知识:质数相关讲解——质数判定,分解质因数及筛质数
算法·质数·数学知识
想进个大厂2 小时前
代码随想录day35 36
算法·leetcode·职场和发展
BackCatK Chen2 小时前
第十三章 C 语言中的存储类别、链接与 内存管理
c语言·内存管理·static·extern·存储类别·malloc 动态内存
xqqxqxxq2 小时前
洛谷算法1-2 排序(NOIP经典真题解析)java(持续更新)
java·开发语言·算法
嵌入小生0072 小时前
数据结构 | 常用排序算法大全及二分查找
linux·数据结构·算法·vim·排序算法·嵌入式
近津薪荼2 小时前
优选算法——滑动窗口4(找子串)
c++·学习·算法
2301_822377652 小时前
模板代码异常处理
开发语言·c++·算法
hcnaisd22 小时前
基于C++的游戏引擎开发
开发语言·c++·算法
多恩Stone2 小时前
【3DV 进阶-12】Trellis.2 数据处理脚本细节
人工智能·pytorch·python·算法·3d·aigc