跳到主要内容
极客日志极客日志
首页博客AI提示词GitHub精选代理工具
|注册
博客列表

目录

  1. 一、排序概念及运用
  2. 1.1 插入排序
  3. (1)直接插入排序
  4. (2)希尔排序
  5. 1.2 选择排序
  6. (1)直接选择排序
  7. (2)堆排序
C算法

数据结构:常见排序算法详解

本文讲解了数据结构中的排序算法,涵盖插入排序(直接插入、希尔排序)与选择排序(直接选择、堆排序)。详细介绍了各算法原理、C 语言实现代码及时间复杂度。直接插入适合小数据量,希尔排序通过增量优化提升效率;直接选择效率较低,堆排序基于堆结构实现 O(nlogn)。

未来可期发布于 2026/3/29更新于 2026/4/133 浏览
数据结构:常见排序算法详解

一、排序概念及运用

排序在数据结构中是非常重要的一部分,所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。

在生活中也有很多的应用,比如当我们搜索一款产品时,我们可以选择按销量多少的顺序来给我们推荐产品,也可以按照价格高低来给我们推荐产品,所以排序在生活中也是很常见的。

文章配图

1.1 插入排序

(1)直接插入排序

插入排序又分为直接插入排序和希尔排序。直接插入排序是比较好理解的,比如我们日常生活中的扑克牌游戏,当我们拿到牌的时候我们会习惯性的直接将牌按我们想要的顺序排列。

文章配图

那么希尔排序又是怎么回事呢?我用一张清晰的思路图来向大家展示:

文章配图

void InitSort(int* arr, int n) {
    for (int i = 0; i < n - 1; i++) {
        int end = i;
        int tmp = arr[end + 1];
        while (end >= 0) {
            if (arr[end] > tmp) {
                arr[end + 1] = arr[end];
                end--;
            } else {
                break;
            }
        }
        arr[end + 1] = tmp;
    }
}

文章配图

对于直接插入来说,这个算法的时间复杂度是多少呢?代码中有两层嵌套,如果有最坏的情况发生的话,时间复杂度为 O(n^2),但是最好的情况是 O(n)。

(2)希尔排序

我们在直接插入排序中,当数组为降序时,时间复杂度会高一点,此时就要说我们的希尔排序了。希尔排序法又称缩小增量法。希尔排序法的基本思想是:先选定一个整数(通常是 gap = n/3+1),把待排序文件所有记录分成各组,所有的距离相等的记录分在同一组内,并对每一组内的记录进行排序,然后 gap=gap/3+1 得到下一个整数,再将数组分成各组,进行插入排序,当 gap=1 时,就相当于直接插入排序。它是在直接插入排序算法的基础上进行改进而来的,综合来说它的效率肯定是要高于直接插入排序算法的。

总结下来就是第一步预排序,第二步直接插入排序。

文章配图

void ShellSort(int* arr, int n) {
    int gap = n;
    while (gap > 1) {
        gap = gap / 3 + 1;
        for (int i = 0; i < n - gap; i++) {
            int end = i;
            int tmp = arr[end + gap];
            while (end >= 0) {
                if (arr[end] > tmp) {
                    arr[end + gap] = arr[end];
                    end -= gap;
                } else {
                    break;
                }
            }
            arr[end + gap] = tmp;
        }
    }
}

文章配图

对于希尔排序,直接的思路是比较好理解的,但是如果我们写成代码的话,是有点不好理解的,尤其是对于 gap 分组再嵌套进入循环,大家可以借助画图的方法深入理解一下。对于希尔排序的时间复杂度,因为 gap 的取值很多,导致很难去计算,因此很多书中给出的希尔排序的时间复杂度都不固定。但是外层循环的时间复杂度可以直接给出为:O(log2 n) 或者 O(log3 n),即 O(log n)。总之希尔排序的效率是高于直接插入排序的。

1.2 选择排序

选择排序的基本思想:每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。

(1)直接选择排序
  1. 在元素集合 array[i]--array[n-1] 中选择关键码最大 (小) 的数据元素。
  2. 若它不是这组元素中的最后一个 (第一个) 元素,则将它与这组元素中的最后一个(第一个)元素交换。
  3. 在剩余的 array[i]--array[n-2](array[i+1]--array[n-1])集合中,重复上述步骤,直到集合剩余 1 个元素。
Swap(int* a, int* b) {
    int temp;
    temp = *a;
    *a = *b;
    *b = temp;
}

void SelectSort(int* arr, int n) {
    for (int i = 0; i < n; i++) {
        int begin = i;
        int mini = i; //找最小的值
        for (int j = i + 1; j < n; j++) {
            if (arr[j] < arr[mini]) {
                mini = j;
            }
        }
        //找到最小的值了,i 和 mini 位置的数据进行交换
        Swap(&arr[i], &arr[mini]);
    }
}

文章配图

这一部分的算法思路还是很好理解的,我们进行了两次嵌套循环,在每一次中找到最小的值,然后将最小的值放在第一位,同时这个算法的时间复杂度跟我们的直接插入排序是一样的,最差情况是 O(n^2)。但是我们能不能换一个思路,我们在找最小值的情况下能不能直接找最大值,同时进行寻找,那么我们的时间效率会不会提高呢?

void SelectSort2(int* arr, int n)//优化
{
    int begin = 0;
    int end = n - 1;
    while (begin < end) {
        int mini = begin, maxi = begin;
        for (int i = begin + 1; i <= end; i++) {
            if (arr[i] > arr[maxi]) {
                maxi = i;
            }
            if (arr[i] < arr[mini]) {
                mini = i;
            }
        }
        Swap(&arr[mini], &arr[begin]);
        Swap(&arr[maxi], &arr[end]);
        ++begin;
        --end;
    }
}

文章配图

这是我们按照之后的思路写的算法,根据我的代码,我们是同时找最小值和最大值,最后在交换,但是代码出现了问题,最后并没有按我们想要的排序,那么问题到底出现在哪了呢?

文章配图

所以我们还要处理这种特殊的情况,我们就要在交换之前再加上一个 if 条件:

文章配图

文章配图

直接选择排序的特性总结:

  1. 直接选择排序思考非常好理解,但是效率不是很好。实际中很少使用。
  2. 时间复杂度:O(n^2)。
  3. 空间复杂度:O(1)。
(2)堆排序

堆排序也是属于选择排序的一种,堆排序 (Heapsort) 是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。它是通过堆来进行选择数据。需要注意的是排升序要建大堆,排降序建小堆。在前面学习堆的时候我们也详细的讲解过堆排序的原理思路以及详细的代码展示。那么堆排序的时间复杂度是 O(nlogn)。

在插入排序中,希尔排序是直接插入排序的优化,效率提高了不少;在选择排序中,直接选择排序的时间复杂度是比较高的,也就是说这个排序算法的效率是比较低的,在平时的计算中我们是不选择的,但是我们也要了解这种算法。

极客日志微信公众号二维码

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

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

更多推荐文章

查看全部
  • Flutter 三方库 webdriver 的鸿蒙化适配指南
  • 智元机器人三大产线与 5000 台量产里程碑
  • OFA 图文蕴含模型部署:AI 绘画提示词与图像匹配度评分
  • DeepSeek-OCR-WEBUI 高性能 OCR 文本识别部署全流程
  • Trae AI 编程工具使用指南与竞品对比分析
  • 工业具身智能实操指南:从视觉识别到自主执行
  • $19.99 订阅值不值?Google AI Pro 全面评测以及订阅会员权益功能解析详情
  • LangChain 核心组件 RunnableLambda 详解与实战
  • Llama API 集成 LlamaIndex 实现文本补全与结构化提取
  • 华为 OD 机试真题:机器人活动区域
  • node-llama-cpp 错误处理与调试:本地 AI 开发常见问题
  • 地瓜机器人 RDK 系列选型指南:X3 vs X5 vs S100 vs S100P
  • AIGC 时代 C++ 吞吐量优化技巧与性能提升实践
  • JSP 基于身份的在线投票系统设计与实现
  • 主流大模型横评:GPT、Claude、Gemini、Llama 及国产模型选型指南
  • 人工智能:大语言模型(LLM)原理与应用实战
  • Spring MVC 全面详解:Java Web 开发框架
  • AI 提示词技术:人设设定(Character Prompt)让模型“扮演”角色
  • GitHub Copilot 接入第三方模型 API 配置指南
  • VsCode 远程 Copilot 调用 Claude Agent 提示“无效请求”的排查与修正

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,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

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online