归并排序(merge_sort)
最近在学习算法,学到归并排序这里确实有些让人迷惑,主要是一直没能理解递归的具体运行方式。
归并排序是分治法的典型应用,将一整个大问题“分”,然后“治”。对于数组排序来说,“分”的过程就是将整个数组分成单个数字,“治”的过程就是将这些单个数字排序合并。
首先我们应该思考如何合并的过程,在归并排序中,所有的子序列都是有序的,这么来说就好办了:
1 void merge(int[] A, int left, int mid, int right){
2 //两个数组的长度
3 int n1 = mid - left + 1;
4 int n2 = right - mid;
5
6 //复制两个子数组
7 int L[] = new int[n1 + 1];
8 int R[] = new int[n2 + 1];
9 for (int i = 0;i < n1;i++)
10 L[i] = A[left + i];
11 for (int i = 0;i < n1;i++)
12 R[i] = A[mid + i + 1];
13
14 //设置哨兵
15 L[n1] = Integer.MAX_VALUE;
16 R[n2] = Integer.MAX_VALUE;
17
18 //排序过程
19 int i = 0;
20 int j = 0;
21 for (int k = left; k <= right; k++){
22 if(L[i]<=R[j]){
23 A[k] = L[i];
24 i++;
25 }else {
26 A[k] = R[j];
27 j++;
28 }
29 }
30 }
上面的代码里,是将数组A的两个区间合并排序。既然两个数组都有序,那么从头开始,依次比较大小,就能将两个数组合并成一个大的有序的数组。需要注意的是这里在数组最后我们添加了一个哨兵元素,这个元素可以帮我们简化代码,同时在执行时不需要判断数组是否越界。
合并过程既然已经解决,剩下的就是“分”的问题。这里的分有些像二分查找。
/*
*归并排序,分治的思想,先分,再治
*/
void merge_sort(int[] A,int p,int r){
if(p < r){
int q = (p + r)/2;
merge_sort(A,p,q);
merge_sort(A,q + 1,r);
merge(A,p,q,r);
}
}
我觉得理解递归需要逐步运行,一步一步地看递归运行的每一步过程,这样才能真正理解吸收
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】