现在位置: 首页 > C 语言数据结构与算法 > 正文

排序

排序(Sorting)是将一组数据按照特定顺序重新排列的过程,是数据处理中最基础、也是研究最深入的算法问题之一。


排序算法全家福

排序算法全家福 — 时间复杂度与特征对比

基础排序(O(n²))

冒泡排序、选择排序和插入排序实现简单,适合小规模数据或教学理解。

高级排序(O(n log n))

快速排序、归并排序和堆排序在工程中应用最广。希尔排序则是对插入排序的改进。

实例

#include <stdio.h>

void swap(int* a, int* b) { int t = *a; *a = *b; *b = t; }

/* 冒泡排序 — O(n²),稳定
   每轮将最大元素"冒泡"到末尾 */

void bubbleSort(int arr[], int n) {
    for (int i = 0; i < n - 1; i++) {
        int swapped = 0;  /* 优化:提前终止 */
        for (int j = 0; j < n - 1 - i; j++) {
            if (arr[j] > arr[j + 1]) {
                swap(&arr[j], &arr[j + 1]);
                swapped = 1;
            }
        }
        if (!swapped) break;  /* 已有序,提前结束 */
    }
}

/* 快速排序分区函数 — O(n log n) 平均,不稳定
   选基准 pivot,小于 pivot 放左边,大于放右边 */

int partition(int arr[], int low, int high) {
    int pivot = arr[high];  /* 选最后一个元素为基准 */
    int i = low - 1;        /* i 指向小于 pivot 的区域的末尾 */
    for (int j = low; j < high; j++) {
        if (arr[j] < pivot) {
            i++;
            swap(&arr[i], &arr[j]);
        }
    }
    swap(&arr[i + 1], &arr[high]);  /* 基准放到正确位置 */
    return i + 1;
}

void quickSort(int arr[], int low, int high) {
    if (low < high) {
        int pi = partition(arr, low, high);  /* 分区索引 */
        quickSort(arr, low, pi - 1);   /* 递归排序左半部分 */
        quickSort(arr, pi + 1, high);  /* 递归排序右半部分 */
    }
}

void printArray(int arr[], int n) {
    for (int i = 0; i < n; i++) printf("%d ", arr[i]);
    printf("\n");
}

int main() {
    int arr1[] = {64, 34, 25, 12, 22, 11, 90};
    int n1 = 7;
    bubbleSort(arr1, n1);
    printf("冒泡排序: "); printArray(arr1, n1);
    /* 输出: 11 12 22 25 34 64 90 */

    int arr2[] = {64, 34, 25, 12, 22, 11, 90};
    quickSort(arr2, 0, 6);
    printf("快速排序: "); printArray(arr2, 7);
    /* 输出: 11 12 22 25 34 64 90 */
    return 0;
}

分治思想示意

三大 O(n log n) 排序算法 — 分治策略对比

快速排序 (分区)

选基准 pivot

小于基准→左侧,大于→右侧

递归排序左右子数组

不稳定 | 原地 | 最常用

归并排序 (合并)

递归二分至最小单元

合并两个有序子序列

需要额外数组 O(n)

稳定 | 需额外空间 | 外排序

堆排序 (堆化)

建最大堆 O(n)

堆顶(最大)放末尾

重新调整堆 O(log n)

不稳定 | 原地 O(1) | 空间最优

排序算法完整对比

算法最好平均最坏空间稳定性
冒泡排序O(n)O(n²)O(n²)O(1)稳定
选择排序O(n²)O(n²)O(n²)O(1)不稳定
插入排序O(n)O(n²)O(n²)O(1)稳定
快速排序O(n log n)O(n log n)O(n²)O(log n)不稳定
归并排序O(n log n)O(n log n)O(n log n)O(n)稳定
堆排序O(n log n)O(n log n)O(n log n)O(1)不稳定
希尔排序O(n log n)O(n^1.3)O(n²)O(1)不稳定

实际选型建议:通用场景首选快速排序;需要稳定性选归并排序;内存极度受限选堆排序;小规模或基本有序数据选插入排序。