跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C算法

五大经典排序算法详解:插入、希尔、冒泡、选择与堆排序

综述由AI生成五大经典排序算法涵盖插入、希尔、冒泡、选择与堆排序。核心原理涉及逐步构建有序序列、分组增量调整、相邻元素交换及堆结构维护。C 语言实现展示了具体逻辑,时间复杂度从 O(N^2) 到 O(NlogN) 不等,空间复杂度多为 O(1)。稳定性方面,插入和冒泡稳定,其余不稳定。实际应用中需根据数据规模与分布特性选择合适算法。

嘘发布于 2026/3/15更新于 2026/6/515 浏览
五大经典排序算法详解:插入、希尔、冒泡、选择与堆排序

插入排序

核心思想

插入排序的核心在于逐步构建有序序列。想象一下整理扑克牌,每摸到一张新牌,就把它插到手头已排好序的牌堆里合适的位置。初始时,第一个元素被视为有序,后续每个元素都向前查找位置并插入。

文章配图

代码实现
void InsertSort(int* a, int n) {
    // 遍历未排序元素(从第 2 个元素开始)
    for (int i = 1; i < n; i++) {
        int end = i - 1;
        int tmp = a[i];
        // 向前查找合适位置,大于 tmp 则后移(此处为降序逻辑)
        while (end >= 0) {
            if (a[end] < tmp) {
                a[end + 1] = a[end];
                end--;
            } else {
                break;
            }
        }
        a[end + 1] = tmp;
    }
}
性能分析

时间复杂度通常是 O(N^2),但在数据基本有序时能优化到 O(N)。空间复杂度为 O(1),且是稳定排序。适合小规模或近似有序的数据场景。


希尔排序

核心思想

希尔排序是对插入排序的改进,核心是分组插入。先按较大增量将数组分成若干子序列进行插入排序,让整体变得'大致有序',再逐步缩小增量,直到增量为 1 时完成最终排序。这就像先把乱序的牌按花色分组整理,再按点数细分,最后整体微调。

文章配图

不同教材对时间复杂度的分析略有差异,通常认为在 O(NlogN) 到 O(N^2) 之间,取决于增量序列的选择。

代码实现
void ShellSort(int* a,  n) {
     gap = n;
     (gap > ) {
        gap = gap /  + ;
        
         ( j = ; j < gap; j++) {
             ( i = j; i < n - gap; i += gap) {
                 end = i;
                 tmp = a[i + gap];
                 (end >= ) {
                     (tmp > a[end]) { 
                        a[end + gap] = a[end];
                        end -= gap;
                    }  {
                        ;
                    }
                }
                a[end + gap] = tmp;
            }
        }
    }
}
int
int
while
1
3
1
/*-------------一组排完排另一组-------------*/
for
int
0
for
int
int
int
while
0
if
// 降序调整
else
break
性能分析

空间复杂度 O(1),但不稳定。由于跳跃交换可能改变相同值元素的相对顺序。效率优于普通插入排序,尤其在数据量较大时。


选择排序

核心思想

每次从未排序部分选出最小(或最大)的元素,与未排序部分的第一个元素交换。重复此过程直到所有元素归位。就像从一堆打乱的牌里,每次挑出最小的一张放到已整理好的牌堆后面。

文章配图

代码实现

这里展示双向选择排序的优化版本,同时寻找最大值和最小值,减少遍历次数。

void SelectSort(int* a, int n) {
    int left = 0;
    int right = n - 1;
    while (left < right) {
        int max = left;
        int min = left;
        for (int i = left + 1; i <= right; i++) {
            if (a[max] < a[i]) max = i;
            if (a[min] > a[i]) min = i;
        }
        swap(&a[left], &a[min]);
        // 修正:max 有可能和 left 重叠
        if (left == max) {
            max = min;
        }
        swap(&a[right], &a[max]);
        left++;
        right--;
    }
}
性能分析

无论数据是否有序,比较次数固定,时间复杂度始终为 O(N^2)。空间复杂度 O(1),不稳定。效率通常较低,一般不作为首选。


堆排序

核心思想

利用堆(完全二叉树)的特性进行排序。先将数组建成大顶堆,堆顶即为最大值。将堆顶与末尾元素交换,使最大值归位,然后重新调整剩余元素为大顶堆。重复直到有序。

代码实现

包含向上调整和向下调整两个辅助函数,实际排序主要使用向下调整建堆。

// 向下调整算法
void AdjustDown(int* a, int n, int parent) {
    int child = 2 * parent + 1;
    while (child < n) {
        if (child + 1 < n && a[child + 1] > a[child]) {
            child++;
        }
        if (a[child] > a[parent]) {
            swap(&a[child], &a[parent]);
            parent = child;
            child = 2 * parent + 1;
        } else {
            break;
        }
    }
}

// 堆排序
void HeapSort(int* a, int n) {
    // 向下调整建堆 -- O(N)
    for (int i = (n - 2) / 2; i >= 0; i--) {
        AdjustDown(a, n, i);
    }
    // 排序阶段
    int end = n - 1;
    while (end > 0) {
        swap(&a[0], &a[end]);
        AdjustDown(a, end, 0);
        end--;
    }
}
性能分析

建堆 O(N),排序阶段 N 次调整每次 O(logN),总时间复杂度 O(NlogN)。不受数据分布影响,空间复杂度 O(1),但不稳定。适合对稳定性要求不高但需要保证最坏情况性能的场景。


冒泡排序

核心思想

通过相邻元素的比较与交换,让较大(较小)的元素逐步'冒泡'到数组末尾。每一轮遍历后,当前未排序部分的最大值会被推到末尾。

文章配图

代码实现

加入标志位优化,若某一趟未发生交换则说明已有序,可提前结束。

void BubbleSort(int* a, int n) {
    for (int i = 0; i < n - 1; i++) {
        int flag = 0;
        for (int j = 1; j < n - i; j++) {
            if (a[j - 1] > a[j]) {
                swap(&a[j - 1], &a[j]);
                flag = 1;
            }
        }
        if (flag == 0) break;
    }
}
性能分析

时间复杂度 O(N^2),优化后最好情况 O(N)。空间复杂度 O(1),稳定。适合教学和小规模数据,实际工程中较少直接使用。


总结对比

算法平均时间复杂度空间复杂度稳定性
插入排序O(N^2)O(1)稳定
希尔排序O(NlogN)~O(N^2)O(1)不稳定
选择排序O(N^2)O(1)不稳定
堆排序O(NlogN)O(1)不稳定
冒泡排序O(N^2)O(1)稳定

选型建议:

  • 数据量小或基本有序:优先插入排序,效率极高。
  • 数据量大且无序:堆排序或快速排序(虽未在此详述,但常作为对比),保证 O(NlogN)。
  • 对稳定性有要求:考虑插入或冒泡(小数据)。
  • 内存受限:上述算法均为原地排序,空间开销极小。

实际开发中,C 标准库 qsort 或 C++ STL std::sort 通常基于混合策略(如 IntroSort),综合了多种算法的优势,建议直接调用而非手写底层实现。

目录

  1. 插入排序
  2. 核心思想
  3. 代码实现
  4. 性能分析
  5. 希尔排序
  6. 核心思想
  7. 代码实现
  8. 性能分析
  9. 选择排序
  10. 核心思想
  11. 代码实现
  12. 性能分析
  13. 堆排序
  14. 核心思想
  15. 代码实现
  16. 性能分析
  17. 冒泡排序
  18. 核心思想
  19. 代码实现
  20. 性能分析
  21. 总结对比
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • M2LOrder 服务优化:API 响应压缩与 WebUI 资源懒加载
  • Linux 用户管理与系统监控基础操作
  • Stable-Diffusion-3.5 提升生成质量:FP8+ComfyUI 调优指南
  • AI 时代普通人创作指南:工具选择与实战技巧
  • 基于 .NET 8 Web API 的 RabbitMQ 消息队列应用
  • VR 视频下载工具 N_m3u8DL-RE 使用指南
  • GitHub Copilot 集成安全风险及防护实践
  • LangGraph 在 LangChain 中的应用:图论驱动的多 Agent 协作
  • Python 基于 Flask 的小区停车场管理系统设计与实现
  • CTF 夺旗赛入门教程:从零开始掌握网络安全竞技
  • Cloudflare 反爬绕过:Canvas/WebGL/WebRTC 多维度浏览器指纹隐身实战
  • AI 大模型应用开发体系化学习路线
  • Kafka 生产者 API 快速上手与 Scala 实现
  • Python 属性描述符:从原理到 ORM 实践详解
  • 飞算 JavaAI 实战:47 分钟重构高耦合遗留系统
  • 动态跟量下单算法(POV)实现与解析
  • 二叉树 DFS 实战:计算布尔值与路径数字和
  • C++ STL 库:unordered_map 与 unordered_set 底层剖析
  • 半小时搭建 AI 量化系统:OpenClaw 与开源三件套实战
  • 大模型入门书籍精选及人工智能基础推荐

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online