C语言递归实现归并排序详解

Owen
Owen
发布时间:2026-10-13| 7人浏览过
原创

归并排序是一种基于分治策略的高效排序算法。本文将深入解析C语言中利用递归来实现归并排序的具体步骤、原理及完整代码。

归并排序的核心逻辑

归并排序(Merge Sort)采用“分而治之”的思想,主要包含两个阶段:

  1. 分割(Divide):将待排序数组从中间划分为左右两个子数组,递归地对左半区和右半区继续进行划分,直到子数组只包含一个元素时停止划分。此时,单个元素的数组天然有序。
  2. 合并(Conquer/Merge):从最底层开始,将两个已排序的子数组合并为一个新的有序数组。比较两个子数组的排头元素,将较小的放入临时数组,并移动对应指针。当其中一个子数组的元素全部处理完后,将另一个子数组剩余的部分直接追加到临时数组末尾。最后将临时数组中的结果复制回原数组。

C语言代码实现与解析

以下代码展示了如何在C语言中完整实现上述逻辑,包含内存分配、递归拆分、合并排序及资源释放的关键步骤。

#include<bits/stdc++.h>
using namespace std;

// 打印数组辅助函数
void print_arr(int arr[], int n){
	for(int i=0; i<n; i++){
		printf("%d ", arr[i]);
	}
	printf("\n"); 
}

/**
 * 合并两个有序子数组
 * @param arr     原数组
 * @param tempArr 临时数组,用于存储合并后的结果
 * @param left    左半区的起始索引
 * @param mid     左半区的结束索引(右半区的起始位置为 mid+1)
 * @param right   右半区的结束索引
 */
void merge(int arr[], int tempArr[], int left, int mid, int right){
	int l_pos = left;       // 左半区当前未排序元素的起始位置
	int r_pos = mid + 1;    // 右半区当前未排序元素的起始位置
	int pos = left;         // 临时数组当前写入位置的起始位置

	// 当左右半区都还有元素时,进行比较并填入临时数组
	while(l_pos <= mid && r_pos <= right) {
		if(arr[l_pos] < arr[r_pos]) { // 左半区元素较小
			tempArr[pos++] = arr[l_pos++];
		} else { // 右半区元素较小或相等
			tempArr[pos++] = arr[r_pos++];
		}
	}

	// 如果左半区仍有剩余元素,将其追加到临时数组
	while(l_pos <= mid) tempArr[pos++] = arr[l_pos++];

	// 如果右半区仍有剩余元素,将其追加到临时数组
	while(r_pos <= right) tempArr[pos++] = arr[r_pos++];

	// 将临时数组中排好序的元素拷贝回原数组
	pos = left;
	while(pos <= right) {
		arr[pos] = tempArr[pos];
		pos++;
	}
}

/**
 * 递归执行归并排序
 * @param arr     原数组
 * @param tempArr 临时数组
 * @param left    当前待排序区间的左边界
 * @param right   当前待排序区间的右边界
 */
void msort(int arr[], int tempArr[], int left, int right){
	// 基准条件:如果区间只有一个元素或为空,则无需进一步划分
	if(left < right) {
		int mid = (left + right) / 2;
		
		// 递归对左半区进行排序
		msort(arr, tempArr, left, mid);
		// 递归对右半区进行排序
		msort(arr, tempArr, mid + 1, right);
		
		// 将两个已排序的半区合并
		merge(arr, tempArr, left, mid, right);
	}
}

/**
 * 归并排序入口函数
 * @param arr 待排序数组
 * @param n   数组大小
 */
void merge_sort(int arr[], int n){
	// 动态分配临时数组,避免在栈上重复分配
	int* tempArr = (int*)malloc(n * sizeof(int));
	if(tempArr != NULL) {
		// 调用递归排序函数,处理范围从 0 到 n-1
		msort(arr, tempArr, 0, n - 1);
		// 释放临时数组内存
		free(tempArr);
	} else {
		printf("Memory allocation failed!");
	}
}

int main() {
	int arr[] = {9, 5, 2, 7, 12, 4, 3, 1, 11};
	int n = 9;

	printf("原始数组: ");
	print_arr(arr, n);

	// 执行归并排序
	merge_sort(arr, n);

	printf("排序后数组: ");
	print_arr(arr, n);

	return 0;
}

关键点说明

  • 时间复杂度:归并排序在任何情况下(最好、最坏、平均)的时间复杂度均为 O(n log n),因为每次都将问题规模减半,且合并过程需要遍历所有元素。
  • 空间复杂度:由于需要额外的临时数组来存储合并结果,空间复杂度为 O(n)。代码中通过 malloc 在入口处一次性分配内存,比在每次递归中分配更高效。
  • 稳定性:归并排序是稳定的排序算法。在 merge 函数中,当 arr[l_pos] == arr[r_pos] 时,优先选择左边的元素,从而保持了相等元素的相对顺序。

以上就是C语言递归实现归并排序的详细教程,更多关于C语言算法的文章,敬请关注本站!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。