JS版 + Java版 归并排序示例代码
Code(Java):
import java.util.Arrays;
/**
* 归并排序
*/
public class MergeSort {
/**
* 私有化
*/
private MergeSort() {}
/**
* 归并排序的sort方法
* @param arr 待排序数组
* @param <E> 可比较的元素
*/
public static <E extends Comparable<E>> void sort(E[] arr) {
sort(arr, 0, arr.length - 1);
}
/**
* 内部sort方法
* @param arr 待排序数组
* @param l 左边界索引
* @param r 右边界索引
* @param <E> 元素类型(必须可比较)
*/
private static <E extends Comparable<E>> void sort(E[] arr, int l, int r) {
// 递归终止条件
if (l >= r) {
return;
}
// 分为两部分,取其中间索引(分治)
int mid = (l + r) / 2;
sort(arr, l, mid);
sort(arr, mid + 1, r);
// 将排好序的两部分合二为一(合并)
merge(arr, l, mid, r);
}
/**
* 合并两个有序的区间 arr[l, mid] 和 arr[mid+1, r]
* @param arr 待排序数组(整个数组或部分)
* @param l 数组索引的左边界
* @param mid 数组的中间索引
* @param r 数组索引的右边界
* @param <E> 元素类型
*/
private static <E extends Comparable<E>> void merge(E[] arr, int l, int mid, int r) {
// 备份数组的[l, r]区间
E[] tmp = Arrays.copyOfRange(arr, l, r + 1);
// 指针i,指向左半部的开头
int i = l;
// 指针j,指向右半部的开头
int j = mid + 1;
// 为[l, r]区间的arr排序
for (int k = l; k <= r; k++) {
// 如果i指针移动到了mid之外(右)
// 则说明数组左侧部分已经全部遍历过了
if (i > mid) {
arr[k] = tmp[j - l];
j++;
}
// 如果j指针也移动出了r边界
// 则数组左侧部分已经完成遍历,这时处理左数组即可
else if (j > r) {
arr[k] = tmp[i - l];
i++;
}
// 如果i指针在左半边数组的索引范围内
// 且j指针也在右半边数组的索引范围之内
// 则比较i,j两索引上的元素大小
else if (tmp[i - l].compareTo(tmp[j - l]) <= 0) {
// tmp[i] <= tmp[j]
arr[k] = tmp[i - l];
i++;
}
// 剩下的一种情况,i,j均未越界,且tmp[i] > tmp[j]
else {
arr[k] = tmp[j - l];
j++;
}
}
}
public static void main(String[] args) {
Integer[] arr = {9, -1, 5, 8, 2, 17, 7, 0, 6};
MergeSort.sort(arr);
for (int item : arr) {
System.out.println(item);
}
}
}
Code(JavaScript):
/**
* 合并区间
* @param {number[]} nums
* @param {number} l
* @param {number} r
* @param {number} m
*/
function merge(nums, l, r, m) {
const size = r - l + 1;
// 暂存l-r闭区间范围内合并后的数据
const tmp = new Array(size);
let i = l;
let j = m + 1;
let k = 0;
// 当左右子数组还存在元素时,两两比较,并将小者保存到tmp中
while (i <= m && j <= r) {
if (nums[i] <= nums[j]) {
tmp[k++] = nums[i++];
}
else {
tmp[k++] = nums[j++];
}
}
// 将左右子数组剩余的元素复制到tmp中
while (i <= m) {
tmp[k++] = nums[i++];
}
while (j <= r) {
tmp[k++] = nums[j++];
}
// 将tmp中的值复制到对应的nums范围之中
for (k = 0; k < size; k++) {
nums[l + k] = tmp[k];
}
}
/**
* 归并处理
* @param {number[]} nums
* @param {number} l
* @param {number} r
*/
function _mergeSort(nums, l, r) {
if (l >= r) {
return;
}
// 划分两部分进行处理
const m = l + Math.floor((r - l) / 2);
_mergeSort(nums, l, m); // 处理当前的左半部
_mergeSort(nums, m + 1, r); // 处理当前的右半部
// 合并两部分
merge(nums, l, r, m);
}
/**
* 归并排序
* @param {number[]} nums
*/
function mergeSort(nums) {
const l = 0;
const r = nums.length - 1;
_mergeSort(nums, l, r);
}
//// 调用示例
// var arr = [5,2,0,3,4,9,-1];
// mergeSort(arr);
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!