1. 排序算法
(1)简单排序(适合小规模数据)
算法 | 核心思想 | 时间复杂度 | 特点 |
---|
冒泡排序 | 相邻元素比较交换,每轮将最大值冒泡到末尾 | 最差/平均:O(n²) | 稳定,原地排序,代码简单 |
选择排序 | 每轮选择最小元素放到已排序区间末尾 | 最差/平均:O(n²) | 不稳定(交换破坏顺序),原地 |
插入排序 | 将未排序元素插入已排序区间的正确位置 | 最差/平均:O(n²) | 稳定,原地,适合近乎有序的数据 |
(2)高效排序(大规模数据首选)
算法 | 核心思想 | 时间复杂度 | 特点 |
---|
归并排序 | 分治法,递归拆分后合并有序子数组 | 最差/平均:O(n log n) | 稳定,非原地(需O(n)空间) |
快速排序 | 分治法,选取基准值分区(左小右大) | 平均:O(n log n),最差O(n²) | 不稳定,原地排序,实际最快 |
堆排序 | 构建大顶堆,交换堆顶与末尾元素并调整 | 最差/平均:O(n log n) | 不稳定,原地,适合动态数据流 |
关键对比:
- 快速排序:平均性能最优,但最差情况需优化(如随机化基准值)。
- 归并排序:稳定且时间复杂度稳定,但空间开销大。
- 实际应用:
- Python的
list.sort()
使用Timsort(归并+插入排序混合)。 - C++的
std::sort()
基于快速排序+插入排序优化。
2. 查找算法
(1)顺序查找(线性查找)
- 思想:逐个遍历元素,直到找到目标。
- 复杂度:O(n)
- 适用场景:无序数据或数据量极小。
(2)二分查找
- 前提:数据必须有序。
- 思想:每次比较中间元素,缩小一半搜索范围。
- 复杂度:O(log n)
- 变种:
- 查找第一个/最后一个等于目标值的位置。
- 查找插入位置(如Python的
bisect
模块)。
- 应用:数据库索引、内存中的有序集合查询。
3. 图算法
(1)深度优先搜索(DFS)
- 思想:递归或栈实现,尽可能深地探索分支,回溯后继续。
- 复杂度:O(V+E)(V为顶点数,E为边数)
- 应用:
- 拓扑排序(如任务调度)。
- 连通分量检测(如Tarjan算法)。
(2)广度优先搜索(BFS)
- 思想:队列实现,逐层遍历所有邻居。
- 复杂度:O(V+E)
- 应用:
- 无权图的最短路径(如迷宫问题)。
- 社交网络中的“好友推荐”。
(3)Dijkstra算法(单源最短路径)
- 前提:图中无负权边。
- 思想:贪心策略,每次选择当前距离起点最近的顶点松弛其邻居。
- 复杂度:O((V+E) log V)(优先队列优化后)
- 应用:路由协议(如OSPF)、地图导航。
(4)Prim与Kruskal算法(最小生成树-MST)
算法 | 核心思想 | 时间复杂度 | 适用场景 |
---|
Prim | 贪心,从任意顶点逐步扩展最小边 | O(E log V)(堆优化) | 稠密图(邻接矩阵) |
Kruskal | 按边权排序,依次选择不形成环的边 | O(E log E)(并查集) | 稀疏图(邻接表) |
应用:网络布线、电路设计。
关键问题与优化
问题 | 解决方案 | 示例 |
---|
快速排序最差情况 | 随机化基准值或三数取中法 | C++ std::sort() 的混合策略 |
Dijkstra负权边失效 | 改用Bellman-Ford或SPFA算法 | 金融网络中的套利检测 |
二分查找边界条件 | 统一使用左闭右开区间([low, high) ) | Python bisect.bisect_left() |
现代演进方向
- 并行算法:
- 归并排序的MapReduce实现(大数据处理)。
- GPU加速的快速排序(如CUDA Thrust库)。
- 近似算法:
- 针对大规模图的近似最短路径(如Landmark算法)。
- 混合策略:
- 内省排序(Introsort):快速排序+堆排序+插入排序(如C++ STL)。
掌握这些基础算法是解决复杂问题的基石(如快速排序的分治思想可扩展至Top K问题,DFS/BFS是回溯和动态规划的基础)。