排序是程序设计中最基础也最核心的算法场景之一,不同排序算法的时间复杂度、适用场景差异显著。本文将结合归并排序、快速排序、插入排序、选择排序、冒泡排序这 5 种经典排序算法的代码实现,拆解其核心逻辑,并附上一个趣味运算案例,帮助你彻底掌握排序算法的底层原理。
一、排序算法合集:代码 + 核心逻辑
以下是 5 种排序算法的完整实现与关键解析(基于用户输入的数组动态排序)。
1. 归并排序:分治思想的经典实现
核心逻辑:将数组不断拆分为子数组,递归排序子数组后合并,是稳定的 O (nlogn) 复杂度算法。
c
运行
#include <stdio.h>
#include <stdlib.h>
// 合并两个有序子数组
void merge(int a[], int left, int mid, int right) {
int len1 = mid - left + 1; // 左子数组长度
int len2 = right - mid; // 右子数组长度
int *L = (int *)malloc(len1 * sizeof(int));
int *R = (int *)malloc(len2 * sizeof(int));
// 拷贝数据到临时数组
for (int i = 0; i < len1; i++) L[i] = a[left + i];
for (int j = 0; j < len2; j++) R[j] = a[mid + 1 + j];
// 双指针合并
int i = 0, j = 0, k = left;
while (i < len1 && j < len2) {
if (L[i] <= R[j]) a[k++] = L[i++];
else a[k++] = R[j++];
}
// 处理剩余元素
while (i < len1) a[k++] = L[i++];
while (j < len2) a[k++] = R[j++];
free(L);
free(R);
}
// 归并排序递归函数
void mergesort(int a[], int left, int right) {
if (left >= right) return; // 子数组长度≤1时终止
int mid = (left + right) / 2;
mergesort(a, left, mid); // 排序左子数组
mergesort(a, mid + 1, right);// 排序右子数组
merge(a, left, mid, right); // 合并有序子数组
}
2. 快速排序:高效的分治排序(平均 O (nlogn))
核心逻辑:选基准值,将数组分为 “≤基准” 和 “≥基准” 两部分,递归排序子数组。
c
运行
void quicksort(int a[], int left, int right) {
if (left >= right) return;
int i = left, j = right;
int pivot = a[i]; // 选左边界为基准
while (i < j) {
// 从右找第一个<基准的元素
while (i < j && a[j] >= pivot) j--;
a[i] = a[j];
// 从左找第一个>基准的元素
while (i < j && a[i] <= pivot) i++;
a[j] = a[i];
}
a[i] = pivot; // 基准归位
quicksort(a, left, i - 1); // 排序左子数组
quicksort(a, i + 1, right); // 排序右子数组
}
3. 插入排序:适合小规模数据(O (n²))
核心逻辑:将元素逐个插入已排序区域的对应位置,类似整理扑克牌。
c
运行
void insertsort(int a[], int n) {
int i, j, temp;
// 遍历未排序区域
for (i = 1; i < n; i++) {
temp = a[i]; // 取出当前元素
j = i - 1;
// 已排序区域中比temp大的元素后移
while (j >= 0 && a[j] > temp) {
a[j + 1] = a[j];
j--;
}
a[j + 1] = temp; // 插入到正确位置
}
}
4. 选择排序:每次选最小元素交换(O (n²))
核心逻辑:遍历未排序区域,找到最小元素,与当前位置交换。
c
运行
// 交换函数
void swap(int *x, int *y) {
int temp = *x;
*x = *y;
*y = temp;
}
void selectsort(int a[], int n) {
int i, j, min;
for (i = 0; i < n - 1; i++) {
min = i; // 假设当前位置是最小值
// 找未排序区域的最小值下标
for (j = i + 1; j < n; j++) {
if (a[j] < a[min]) min = j;
}
swap(&a[i], &a[min]); // 交换到当前位置
}
}
5. 冒泡排序:相邻元素两两比较(O (n²))
核心逻辑:相邻元素逆序则交换,大元素逐步 “冒泡” 到尾部。
c
运行
void bubblesort(int a[], int n) {
int i, j;
for (i = 0; i < n; i++) {
// 每轮将最大元素推到尾部,减少遍历次数
for (j = 0; j < n - i - 1; j++) {
if (a[j] > a[j + 1]) {
swap(&a[j], &a[j + 1]);
}
}
}
}
二、排序算法的统一调用示例
以下是 “用户输入数组→选择排序算法→输出结果” 的完整程序:
c
运行
#include <stdio.h>
#include <stdlib.h>
// (此处需包含上述排序函数、swap函数)
int main() {
int n;
printf("请输入数组长度:");
scanf("%d", &n);
if (n <= 0) {
printf("错误:数组长度必须为正数!\n");
return 1;
}
int a[n];
printf("请输入数组元素(空格分隔):");
for (int i = 0; i < n; i++) {
scanf("%d", &a[i]);
}
// 选择排序算法(以归并排序为例,可替换为其他排序函数)
mergesort(a, 0, n - 1);
printf("排序后的数组:");
for (int i = 0; i < n; i++) {
printf("%d ", a[i]);
}
printf("\n");
return 0;
}
三、趣味运算案例:交替求和
除了排序,我们再看一个 C 语言运算案例:计算1 - 3 + 5 - 7 + ... + 99 - 101的结果。
c
运行
#include<stdio.h>
int main() {
int i;
int sum=0;
int flag=1; // 符号标记,1为正,-1为负
for(i=1;i<102;i+=2) { // 遍历1、3、5...101
sum+=flag*i;
flag=-flag; // 符号交替
}
printf("%d\n", sum); // 输出结果:-51
return 0;
}
四、算法选型建议
| 算法 | 时间复杂度(平均) | 稳定性 | 适用场景 |
|---|---|---|---|
| 归并排序 | O(nlogn) | 稳定 | 大规模数据、需要稳定排序 |
| 快速排序 | O(nlogn) | 不稳定 | 大规模数据(效率最高) |
| 插入排序 | O(n²) | 稳定 | 小规模数据、基本有序数据 |
| 选择排序 | O(n²) | 不稳定 | 数据量小、交换成本低的场景 |
| 冒泡排序 | O(n²) | 稳定 | 教学演示(实际效率较低) |
通过以上代码与解析,你可以快速掌握 5 种经典排序算法的实现与适用场景,同时理解 C 语言中数组操作、递归、循环的核心用法。可以将代码直接复制到编译器中运行,观察不同算法的排序效果哦!