算法学习笔记(2)——归并排序
归并排序
归并排序的思想是基于分治法,其思路是:
- 将待排序区间平分成左右两半,左右两侧分别递归地做归并排序。
- 将这两个有序的区间合并(每次落一个较小的下来),就将这个区间排好序了。
归并排序相比快速排序,几乎没有什么难理解的边界问题。要注意代码中的q[i] <= q[j]
时从左半边落下元素,如果改成q[i] < q[j]
也是能正确排序的,但是这样会丢失【归并排序是稳定的】这个特性。要保持这个特性,在排序字段相等的时候,应该落下来自左侧区间的元素,所以这里用<=
。
我们知道,归并排序的过程中,需要对当前区间进行对半划分,直到区间的长度为1
。也就是说,每一层的子区间,长度都是上一层的1/2
。这也就意味着,当划分到第 层的时候,子区间的长度就是1
了。
而归并排序的merge
操作,则是从最底层开始(子区间为1的层),对相邻的两个子区间进行合并,对于每一层来说,在合并所有子区间的过程中, 个元素都会被操作一次,所以每一层的时间复杂度都是 。而之前我们说过,归并排序划分子区间,将子区间划分为只剩 个元素,需要划分 次。每一层的时间复杂度为 ,共有 层,所以归并排序的时间复杂度就是。
#include <iostream>
using namespace std;
const int N = 100010;
int n;
int q[N], tmp[N];
void merge_sort(int q[], int l, int r)
{
if (l >= r) return;
int mid = l + r >> 1;
merge_sort(q, l, mid), merge_sort(q, mid + 1, r);
int i = l, j = mid + 1, k = 0;
while (i <= mid && j <= r) {
if (q[i] < q[j]) tmp[k ++] = q[i ++];
else tmp[k ++] = q[j ++];
}
while (i <= mid) tmp[k ++] = q[i ++];
while (j <= r) tmp[k ++] = q[j ++];
for (int i = l, j = 0; i <= r; i ++, j ++ ) q[i] = tmp[j];
}
int main()
{
cin >> n;
for (int i = 0; i < n; i ++ ) cin >> q[i];
merge_sort(q, 0, n - 1);
for (int i = 0; i < n; i ++ ) cout << q[i] << ' ';
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」