数据结构——直接插入排序

直接插入排序

在日常整理扑克牌时,我们通常会把抓到的新牌插入到已整理好的牌堆里,保持牌堆始终有序------直接插入排序的思想与此完全一致。它将待排序数组分为"已排序区间"和"未排序区间",每次从"未排序区间"取出第一个元素,插入到"已排序区间"的合适位置,最终让整个数组有序。

1. 直接插入排序的执行流程

我们以数组arr = {49, 38, 65, 97, 76, 13, 27, 49}为例,详细展示直接插入排序的每一步:

  • 初始状态 :已排序区间只有arr[0] = 49,未排序区间为{38, 65, 97, 76, 13, 27, 49}
  • 第1次插入(处理38)
    取未排序区间第一个元素38,与已排序区间的49比较,38 < 49,所以将49后移一位,把38插入到arr[0]位置。此时数组变为{38, 49, 65, 97, 76, 13, 27, 49},已排序区间为{38, 49}
  • 第2次插入(处理65)
    取未排序区间第一个元素65,与已排序区间的49比较,65 > 49,直接插入到49后面。数组变为{38, 49, 65, 97, 76, 13, 27, 49},已排序区间为{38, 49, 65}
  • 第3次插入(处理97)
    97,与65比较,97 > 65,直接插入到65后面。数组不变,已排序区间扩展为{38, 49, 65, 97}
  • 第4次插入(处理76)
    76,与97比较,76 < 97,将97后移;再与65比较,76 > 65,将76插入到6597之间。数组变为{38, 49, 65, 76, 97, 13, 27, 49}
  • 后续插入(处理13、27、49)
    按照同样逻辑,13会被插入到最前面,27插入到13之后,最后一个49会插入到已排序区间中第一个49的后面(保持相同元素的相对顺序,体现算法稳定性)。最终数组变为{13, 27, 38, 49, 49, 65, 76, 97}
2. 直接插入排序的代码实现

以下是直接插入排序的C语言实现,代码简洁且注释详细,清晰体现"取元素-找位置-插入"的逻辑:

c 复制代码
void InsertSort(int arr[], int n) {
    int i, j, temp;
    for (i = 1; i < n; i++) {  // 外层循环:未排序区间从i=1开始
        temp = arr[i];         // 取出未排序区间的第一个元素
        for (j = i - 1; j >= 0 && arr[j] > temp; j--) {
            arr[j + 1] = arr[j];  // 已排序元素后移,腾出插入位置
        }
        arr[j + 1] = temp;     // 将temp插入到合适位置
    }
}

代码说明:

  • 外层循环i遍历"未排序区间"的起始位置(从第2个元素开始,因为第1个元素默认在已排序区间);
  • 内层循环j从"已排序区间"的末尾向前找,若arr[j] > temp,则将arr[j]后移一位,直到找到arr[j] <= temp的位置;
  • 最后将temp插入到arr[j+1]的位置,完成一次插入。
3. 直接插入排序的性能与特性
  • 时间复杂度
    • 最好情况(数组已完全有序):只需比较n-1次,无需移动元素,时间复杂度为O(n)O(n)O(n);
    • 最坏情况(数组完全逆序):每次插入都要移动已排序区间的所有元素,时间复杂度为O(n2)O(n^2)O(n2);
    • 平均情况:时间复杂度为O(n2)O(n^2)O(n2)。
  • 空间复杂度 :仅需一个临时变量temp,空间复杂度为O(1)O(1)O(1)。
  • 稳定性 :由于相同元素插入时会放在已有相同元素的后面,不会改变相对顺序,因此直接插入排序是稳定的
4. 适用场景

直接插入排序适合以下场景:

  • 数据量较小的数组(如n < 100),此时O(n2)O(n^2)O(n2)的时间复杂度可接受;
  • 数组基本有序的情况(如只有少数元素位置不对),此时比较和移动次数极少,效率接近O(n)O(n)O(n);
  • 对内存开销敏感的场景,因为其空间复杂度仅为O(1)O(1)O(1)。

综上,直接插入排序是一种逻辑直观、实现简单的排序算法,核心是"逐步构建有序区间,每次插入一个元素"。它在小规模或基本有序的数组上表现高效,且具有稳定性,是插入排序家族的基础算法。理解其"插入-移动"的过程,能为后续学习折半插入、希尔排序等进阶算法奠定基础。

相关推荐
依然鸣30 分钟前
PTA团体程序设计天梯赛L1真题讲解L1-077-080
开发语言·c++·算法·深度优先·pat考试·图论
qeen873 小时前
【数据结构】自平衡二叉搜索树各种旋转算法原理解析及AVL树的C++实现
数据结构·c++·算法
lucas_AI3 小时前
1.2B 小模型赢过 235B 大模型:NaviDC-OCR 把文档解析卷明白了
人工智能·深度学习·算法
冻柠檬飞冰走茶4 小时前
PTA基础编程题目集 7-35有理数均值(C++语言实现)
开发语言·数据结构·c++·算法·均值算法
民乐团扒谱机4 小时前
【微实验】倒谱算法(Cepstrum)深度解析:原理、数学推导与代码实现
人工智能·算法·语音识别
Nil2085 小时前
leetcode 189轮转数组
数据结构·算法·leetcode
-dzk-6 小时前
【动态规划】LC 118.杨辉三角
算法·动态规划
恣逍信点6 小时前
《凌微经》静态自悖——变化之自因
人工智能·科技·算法·机器学习·业界资讯·拓扑学·哲学
吃着火锅x唱着歌6 小时前
LeetCode 3885.设计事件管理器
算法·leetcode·职场和发展
土司大王6 小时前
LeetCode hto100——字母异位词分组
java·算法·leetcode