1. 归并排序定义
将数组分为两部分,对每一部分递归进行归并排序。在两部分都排好序后,对它们进行归并。
2. 算法思想
递归调用持续将数组划分为子数组,直到每个子数组只包含一个元素;
将这些小的子数组归并为稍大的有序子数组,直到最后形成一个有序的数组。
实例分析:
数组: 2 9 5 4 8 1 6 7
/ \ ---
拆分: 2 9 5 4 8 1 6 7 |
/ \ / \ |
拆分: 2 9 5 4 8 1 6 7 | ==> "分"
/ \ / \ / \ / \ |
拆分: 2 9 5 4 8 1 6 7 ---|
\ / \ / \ / \ / ---
归并: 2 9 4 5 1 8 6 7 |
\ / \ / | ==> "治"
归并: 2 4 5 9 1 6 7 8 |
\ / |
归并: 1 2 4 5 6 7 8 9 ---|
public void mergeSort(int[] nums) {
int len = nums.length;
if (len > 1) {
// nums数组的前半部分的副本
int[] firstHalf = new int[len / 2];
System.arraycopy(nums, 0, firstHalf, 0, len / 2);
mergeSort(firstHalf);
// nums数组的后半部分的副本
int[] secondHalf = new int[len - len / 2];
System.arraycopy(nums, len / 2, secondHalf, 0, len - len / 2)
mergeSort(secondHalf);
// 归并两个已排序的数组
int[] temp = merge(firstHalf, secondHalf);
// 把新的有序数组temp赋给原始数组nums
System.arraycopy(temp, 0, nums, 0, temp.length);
}
}
// 归并两个已排序的数组
private int[] merge(int[] list1, int[] list2) {
int len1 = list1.length;
int len2 = list2.length;
// 两个数组归并为一个新的有序数组temp
int[] temp = new int[len1 + len2];
int curr_index1 = 0;
int curr_index2 = 0;
int curr_index_temp = 0;
while (curr_index1 < len1 && curr_index2 < len2) {
// 将两个数组中较小的元素存入temp数组
if (list1[curr_index1] < list2[curr_index2]) {
temp[curr_index_temp++] = list1[curr_index1++];
} else {
temp[curr_index_temp++] = list1[curr_index2++];
}
}
// 查看list1中元素是否有剩余
while (curr_index1 < len1) {
temp[curr_index_temp++] = list1[curr_index1++];
}
// 查看list2中元素是否有剩余
while (curr_index2 < len2) {
temp[curr_index_temp++] = list1[curr_index2++];
}
return remp;
}
3. 归并排序时间复杂度
时间复杂度为 O(nlogn)
4. 总结
归并排序算法优于
选择排序、插入排序、冒泡排序。
java.util.Arrays类中的 sort 方法是使用归并排序
算法的变体实现的。