经典算法之归并排序

1|0归并逻辑

归并是采用分治和递归的思想完成的,主要是将数组分成多个小数组,保证小数组内数字有序。
例如:

1, 0, 4, 3, 7, 10, 5, 9
分治之后会形成 1,0,4,3,7,10,5,9 八个只含有一个数字的数组,并保证每一个子数组有序
然后进行合并 1,0, 形成 0,1然后4,3,形成 3,4, 依次类推 最后形成 单个有序子数组
再将数组合并 递归调用 最后形成完整有序数组

2|0代码实现

//定义一个数组用于存储中间过程数据 int[] tmp; public int[] sortArray(int[] nums) { // 初始化中间数组 tmp = new int[nums.length]; mergeSort(nums, 0, nums.length - 1); return nums; } private void mergeSort(int[] nums, int l, int r) { if (l >= r) return; int mid = (l + r) >> 1; // 因为排序要对所有元素 索引 包含mid mergeSort(nums, l, mid); mergeSort(nums, mid + 1, r); // 因为mid 为左数组临界 索引j不能包含mid int i = l, j = mid + 1; int cnt = 0; // 进行分治 mid 为左数组临界 r为右数组临界 l,mid + 1 分别为左右数组开始临界 while (i <= mid && j <= r) { if (nums[i] <= nums[j]) { tmp[cnt++] = nums[i++]; } else { tmp[cnt++] = nums[j++]; } } while (i <= mid) { tmp[cnt++] = nums[i++]; } while (j <= r) { tmp[cnt++] = nums[j++]; } for (int k = 0; k < r - l + 1; k++) { nums[k + l] = tmp[k]; } }

讲解:
定义 mergeSort(nums, l, r) 函数表示对 nums 数组里 [l,r] 的部分进行排序,整个函数流程如下:
1. 递归调用函数 mergeSort(nums, l, mid) 对 nums 数组里 [l,mid] 部分进行排序。
2. 递归调用函数 mergeSort(nums, mid + 1, r) 对 nums 数组里 [mid+1,r] 部分进行排序。
3. 此时 nums 数组里 [l,mid] 和 [mid+1,r] 两个区间已经有序,我们对两个有序区间线性归并即可使 nums 数组里 [l,r] 的部分有序。
4. 线性归并的过程并不难理解,由于两个区间均有序,所以我们维护两个指针 i 和 j 表示当前考虑到 [l,mid] 里的第 i 个位置和 [mid+1,r] 的第 j 个位置。

如果 nums[i] <= nums[j] ,那么我们就将 nums[i] 放入临时数组 tmp 中并让 i += 1 ,即指针往后移。否则我们就将 nums[j] 放入临时数组 tmp 中并让 j += 1 。
如果有一个指针已经移到了区间的末尾,那么就把另一个区间里的数按顺序加入 tmp 数组中即可。
这样能保证我们每次都是让两个区间中较小的数加入临时数组里,那么整个归并过程结束后 [l,r] 即为有序的。


__EOF__

本文作者Spoon | Blog
本文链接https://www.cnblogs.com/Spoonblog/p/16594554.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   SpoonBlog  阅读(23)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
点击右上角即可分享
微信分享提示