查找与排序算法:复杂度、稳定性

查找与排序算法:复杂度、稳定性

查找解决关键字定位,排序解决记录重排。算法选择不能只看平均时间复杂度,还要考虑数据是否有序、是否要求稳定、是否允许额外空间以及是否必须保证最坏性能。

顺序查找与折半查找

顺序查找逐项扫描,最好为 O(1),平均和最坏为 O(n),额外空间为 O(1)。哨兵可以减少边界判断,但不改变渐进复杂度。

折半查找要求序列有序,每轮将区间缩小一半:

cpp 复制代码
int left = 0, right = n - 1;
while (left <= right) {
    int mid = left + (right - left) / 2;
    if (a[mid] == key) return mid;
    if (a[mid] < key) left = mid + 1;
    else right = mid - 1;
}
return -1;

时间复杂度为 O(log n),空间复杂度为 O(1)。查找第一个或最后一个重复值时,命中后仍需继续收缩边界。

插入、折半插入与希尔排序

插入排序维护有序前缀,将当前元素插入正确位置。它稳定、原地,对近乎有序数据有效,平均和最坏为 O(n²)。

折半插入排序用二分查找减少比较次数,但数组移动仍为 O(n²),因此总体复杂度不变。

希尔排序按间隔 gap 进行分组插入排序,再逐步缩小间隔到 1。复杂度取决于增量序列,通常不稳定,但比直接插入排序更适合中等规模数据。

冒泡排序

冒泡排序交换相邻逆序元素。加入交换标志后,已经有序时可以提前结束:

cpp 复制代码
for (int end = n - 1; end > 0 && swapped; --end) {
    swapped = false;
    for (int i = 0; i < end; ++i) {
        if (a[i] > a[i + 1]) {
            std::swap(a[i], a[i + 1]);
            swapped = true;
        }
    }
}

最好为 O(n),平均和最坏为 O(n²),稳定且原地,但通常只适合小规模或教学场景。

快速排序

快速排序通过枢轴划分区间:

text 复制代码
partition(l, r)
quick_sort(l, pivot - 1)
quick_sort(pivot + 1, r)

平均复杂度为 O(n log n),最坏为 O(n²),平均递归空间为 O(log n)。随机枢轴、三路划分和小区间插入排序可以减少退化和常数开销。快速排序通常不稳定。

选择排序

选择排序每轮寻找未排序区间的最小元素并交换到前端。比较次数始终为 O(n²),交换次数较少,原地但不稳定。

堆排序

堆排序先建立大根堆,再将堆顶最大元素交换到末尾并恢复堆:

cpp 复制代码
for (int i = n / 2; i >= 1; --i) sift_down(i, n);
for (int end = n; end > 1; --end) {
    swap(a[1], a[end]);
    sift_down(1, end - 1);
}

建堆为 O(n),排序为 O(n log n),额外空间为 O(1),最坏复杂度有保证,但不稳定。

复杂度比较

算法 平均时间 最坏时间 空间 稳定性
顺序查找 O(n) O(n) O(1) -
折半查找 O(log n) O(log n) O(1) -
插入排序 O(n²) O(n²) O(1) 稳定
希尔排序 依增量序列 依增量序列 O(1) 通常不稳定
冒泡排序 O(n²) O(n²) O(1) 稳定
快速排序 O(n log n) O(n²) O(log n) 平均 不稳定
选择排序 O(n²) O(n²) O(1) 不稳定
堆排序 O(n log n) O(n log n) O(1) 不稳定

近乎有序数据可优先考虑插入排序;要求最坏 O(n log n) 且内存严格受限时可考虑堆排序;平均性能和缓存行为重要时常用快速排序;需要保持相等元素相对顺序时必须选择稳定算法或增加稳定化处理。

相关推荐
徐小夕9 小时前
花了3个月,我们做了一款 AI 版的“飞书文档”
前端·算法·github
Robert--cao10 小时前
移动底盘与机械臂联合规划:开源算法与工程实现
算法
小豆庄10 小时前
Mac 上给视频人脸打码:本地工具的依赖、追踪与推理管线
算法·视觉检测·视频·敏捷流程·纹理贴图
星夜离尘5611 小时前
MATLAB 工程实验:从相邻块均值手写重叠 Allan 偏差,数清有效项
算法·matlab·均值算法
careathers12 小时前
【数据结构】从堆到 PriorityQueue:手写一个优先级队列
数据结构
y1su13 小时前
Leetcode 字符串模板
java·数据结构·算法·leetcode·职场和发展·动态规划
residual_fan13 小时前
船用柴油机动态机动工况故障诊断:控制感知仿射网络(CAAN)的技术实现
人工智能·算法·数据挖掘·数据分析
其实防守也摸鱼14 小时前
Cylab在线靶场——CTF中的通用技能
linux·数据库·学习·算法·靶场·ctf·学习网络安全
蓝悦无人机14 小时前
《Planning algorithms》读书笔记——第8章 反馈运动规划
算法·读书笔记·反馈运动规划