数据结构学习笔记 :排序算法详解与C语言实现

目录

  1. 冒泡排序
  2. 插入排序
  3. 选择排序
  4. 快速排序
  5. Shell排序
  6. 归并排序
  7. 算法对比与选择

一、冒泡排序

算法原理

通过重复遍历数组,比较相邻元素并交换位置,将较大的元素逐渐"浮"到数组末尾。

核心代码
c 复制代码
void bubble_sort(int *a, int size) {
    for (int i = 0; i < size - 1; i++) {
        for (int j = 0; j < size - i - 1; j++) {
            if (a[j] > a[j + 1]) {
                int t = a[j];
                a[j] = a[j + 1];
                a[j + 1] = t;
            }
        }
    }
}
时间复杂度
  • 最坏/平均:O(n²)
  • 最好(已排序):O(n)

二、插入排序

算法原理

将数组分为有序区和无序区,逐个将无序区元素插入到有序区的正确位置。

核心代码
c 复制代码
void insert_sort(int *a, int size) {
    for (int i = 1; i < size; i++) {
        int t = a[i];
        int j;
        for (j = i - 1; j >= 0 && a[j] > t; j--) {
            a[j + 1] = a[j];
        }
        a[j + 1] = t;
    }
}
时间复杂度
  • 最坏/平均:O(n²)
  • 最好(已排序):O(n)

三、选择排序

算法原理

每次从未排序部分找到最小值,与当前起始位置交换,逐步构建有序序列。

核心代码
c 复制代码
void sel_sort(int *a, int size) {
    for (int i = 0; i < size - 1; i++) {
        int min_idx = i;
        for (int j = i + 1; j < size; j++) {
            if (a[j] < a[min_idx]) {
                min_idx = j;
            }
        }
        if (min_idx != i) {
            int t = a[i];
            a[i] = a[min_idx];
            a[min_idx] = t;
        }
    }
}
时间复杂度
  • 最坏/平均/最好:O(n²)(交换次数少)

四、快速排序

算法原理

通过分治法,选择基准值(pivot),将数组分为小于和大于基准的两部分,递归排序子数组。

核心代码
c 复制代码
void quick_sort(int *a, int start, int end) {
    if (start >= end) return;
    int i = start, j = end;
    int pivot = a[start]; // 基准值
    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;
    quick_sort(a, start, i - 1);
    quick_sort(a, i + 1, end);
}
时间复杂度
  • 最坏(已排序):O(n²)
  • 平均:O(n log n)
  • 最好:O(n log n)

五、Shell排序

算法原理

通过分组插入排序,逐步减小组间距离(增量),最终实现整体排序。

核心代码
c 复制代码
void shell_sort(int *a, int size) {
    for (int gap = size / 2; gap > 0; gap /= 2) {
        for (int i = gap; i < size; i++) {
            int t = a[i];
            int j;
            for (j = i; j >= gap && a[j - gap] > t; j -= gap) {
                a[j] = a[j - gap];
            }
            a[j] = t;
        }
    }
}
时间复杂度
  • 最坏:O(n^(1.5))
  • 平均:O(n^(1.3))
  • 改进:通过优化增量序列可进一步提升效率。

六、归并排序

算法原理

分治法将数组拆分为子数组,递归排序后合并有序子数组。

核心代码
c 复制代码
void merge_sort(int *a, int start, int end) {
    if (start >= end) return;
    int mid = (start + end) / 2;
    merge_sort(a, start, mid);
    merge_sort(a, mid + 1, end);
    // 合并
    int *temp = (int *)malloc((end - start + 1) * sizeof(int));
    int i = start, j = mid + 1, k = 0;
    while (i <= mid && j <= end) {
        if (a[i] < a[j])
            temp[k++] = a[i++];
        else
            temp[k++] = a[j++];
    }
    while (i <= mid) temp[k++] = a[i++];
    while (j <= end) temp[k++] = a[j++];
    // 复制回原数组
    for (int t = 0; t < k; t++) {
        a[start + t] = temp[t];
    }
    free(temp);
}
时间复杂度
  • 最坏/平均/最好:O(n log n)
  • 空间复杂度:O(n)

七、算法对比与选择

算法 时间复杂度(最坏) 空间复杂度 稳定性 适用场景
冒泡 O(n²) O(1) 稳定 小规模或近有序数据
插入 O(n²) O(1) 稳定 小规模或近有序数据
选择 O(n²) O(1) 不稳定 交换操作成本低的场景
快速 O(n²) O(log n) 不稳定 大规模数据(平均高效)
Shell O(n^(1.5)) O(1) 不稳定 中等规模数据优化插入排序
归并 O(n log n) O(n) 稳定 大规模数据需稳定性时

关键点总结

  1. 稳定性:插入排序、冒泡排序、归并排序是稳定排序,而快速排序、选择排序、Shell排序不稳定。
  2. 空间换时间:归并排序通过额外空间换取更优时间复杂度。
  3. 递归与迭代:快速排序、归并排序依赖递归,Shell排序为迭代实现。

相关推荐
Love__Tay6 分钟前
【学习笔记】Python金融基础
开发语言·笔记·python·学习·金融
笑口常开xpr13 分钟前
数 据 结 构 进 阶:哨 兵 位 的 头 结 点 如 何 简 化 链 表 操 作
数据结构·链表·哨兵位的头节点
XRZaaa1 小时前
常见排序算法详解与C语言实现
c语言·算法·排序算法
@我漫长的孤独流浪1 小时前
数据结构测试模拟题(4)
数据结构·c++·算法
我的golang之路果然有问题1 小时前
云服务器部署Gin+gorm 项目 demo
运维·服务器·后端·学习·golang·gin
Lester_11012 小时前
嵌入式学习笔记 - freeRTOS xTaskResumeAll( )函数解析
笔记·stm32·单片机·学习·freertos
jackson凌2 小时前
【Java学习笔记】Math方法
java·笔记·学习
Humbunklung2 小时前
PySide6 GUI 学习笔记——常用类及控件使用方法(多行文本控件QTextEdit)
笔记·python·学习·pyqt
sealaugh322 小时前
aws(学习笔记第四十三课) s3_sns_sqs_lambda_chain
笔记·学习·aws
阿超爱嵌入式3 小时前
STM32学习之I2C(理论篇)
stm32·嵌入式硬件·学习