数据结构——折半插入排序

折半插入排序

直接插入排序在确定插入位置时,需要逐个比较已排序区间的元素,当已排序区间较长时,比较次数较多。折半插入排序则利用"已排序区间是有序的"这一特性,通过折半查找快速确定插入位置,从而减少比较次数,是对直接插入排序的高效优化。

1. 折半插入排序的执行流程

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

  • 初始状态 :已排序区间为[49],未排序区间为{38, 65, 97, 76, 13, 27, 49}
  • 第1次插入(处理38)
    目标是将38插入到已排序区间[49]的合适位置。
    ① 折半查找插入位置:定义low=0high=0(已排序区间长度为1),计算mid = (low+high)/2 = 0。比较arr[mid]=493838 < 49,所以插入位置在mid左侧,更新high=mid-1=-1,此时low > high,确定插入位置为low=0
    ② 移动元素并插入:将49后移一位,把38插入到arr[0]位置。数组变为{38, 49, 65, 97, 76, 13, 27, 49},已排序区间扩展为[38, 49]
  • 第2次插入(处理65)
    已排序区间为[38, 49],处理未排序区间的65
    ① 折半查找:low=0high=1mid=(0+1)/2=0。比较arr[mid]=386565 > 38,更新low=mid+1=1;再次计算mid=(1+1)/2=1,比较arr[mid]=496565 > 49,更新low=mid+1=2,此时low > high,确定插入位置为low=2
    ② 移动元素并插入:65直接插入到49后面,数组不变,已排序区间扩展为[38, 49, 65]
  • 第3次插入(处理97)
    已排序区间为[38, 49, 65],处理97
    折半查找后,发现97大于已排序区间的最大元素65,直接插入到末尾,数组不变。
  • 第4次插入(处理76)
    已排序区间为[38, 49, 65, 97],处理76
    ① 折半查找:low=0high=3mid=1arr[1]=49 < 76),更新low=2mid=2arr[2]=65 < 76),更新low=3mid=3arr[3]=97 > 76),更新high=2,此时low > high,确定插入位置为low=3
    ② 移动元素并插入:将97后移,把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 BinaryInsertSort(int arr[], int n) {
    int i, j, low, high, mid, temp;
    for (i = 1; i < n; i++) {
        temp = arr[i];            // 取出未排序区间的第一个元素
        low = 0; high = i - 1;   // 已排序区间的范围[low, high]
        while (low <= high) {     // 折半查找插入位置
            mid = (low + high) / 2;
            if (arr[mid] > temp) high = mid - 1;
            else low = mid + 1;
        }
        for (j = i; j > low; j--) {  // 移动元素,腾出插入位置
            arr[j] = arr[j - 1];
        }
        arr[low] = temp;         // 插入元素
    }
}

代码说明:

  • 外层循环i遍历未排序区间的起始位置;
  • 折半查找阶段:通过lowhigh缩小范围,最终low即为插入位置;
  • 元素移动阶段:从i位置开始,将元素后移,直到low位置,再将temp插入。
3. 折半插入排序的性能与特性
  • 时间复杂度
    折半查找的时间复杂度为 O ( log ⁡ n ) O(\log n) O(logn),但元素移动的次数仍与直接插入排序相同,因此整体时间复杂度仍为 O ( n 2 ) O(n^2) O(n2)。不过,由于减少了比较次数,实际运行效率比直接插入排序更高。
  • 空间复杂度 :仅需一个临时变量temp,空间复杂度为 O ( 1 ) O(1) O(1)。
  • 稳定性 :相同元素插入时,相对顺序不会改变,因此折半插入排序是稳定的
4. 适用场景

折半插入排序适合已排序区间较长 的场景,此时折半查找的优势能充分体现,减少大量比较操作。例如,对基本有序的数组进行排序,或数据量中等(如 n n n在几百到几千之间)的情况,它的效率比直接插入排序更优。

综上,折半插入排序通过折半查找优化了"确定插入位置"的过程,在比较次数上有明显优势,且保持了直接插入排序的稳定性和空间效率,是插入排序家族中更高效的实现方式。理解其"折半查找+元素移动"的逻辑,能为后续学习更复杂的排序算法提供思路。

相关推荐
阿巴~阿巴~11 分钟前
IPv4地址转换函数详解及C++容器安全删除操作指南
linux·服务器·c++·网络协议·算法·c++容器安全删除操作·ipv4地址转换函数
TT哇12 分钟前
【面经 每日一题】面试题16.25.LRU缓存(medium)
java·算法·缓存·面试
im_AMBER25 分钟前
数据结构 11 图
数据结构·笔记·学习·图论
SKYDROID云卓小助手43 分钟前
无人设备遥控器之差分信号抗干扰技术
网络·stm32·单片机·嵌入式硬件·算法
美狐美颜SDK开放平台44 分钟前
什么是美颜sdk?美型功能开发与用户体验优化实战
人工智能·算法·ux·直播美颜sdk·第三方美颜sdk·视频美颜sdk
@宁兰1 小时前
算法实现总结 - C/C++
c语言·c++·算法
xiaoye-duck1 小时前
数据结构之二叉树-链式结构(上)
数据结构
Doro再努力2 小时前
2025_11_14洛谷【入门1】数据结构刷题小结
前端·数据结构·算法
蒙奇D索大2 小时前
【算法】回溯算法精讲:从深度优先搜索到剪枝优化
经验分享·笔记·算法·深度优先·剪枝·改行学it
QTreeY1232 小时前
yolov5/8/9/10/11/12/13+deep-oc-sort算法的目标跟踪实现
人工智能·算法·yolo·目标检测·计算机视觉·目标跟踪