这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战
一、实现代码(java)
private int[] T;
private void mergeSort(int[] arr) {
int n = arr.length;
T = new int[n];
sort(arr,0,n - 1);
}
private void sort(int[] arr,int left,int right) {
if (left >= right) return;
int mid = left + ((right - left) >> 1);
sort(arr,left,mid);
sort(arr,mid + 1,right);
merge(arr,left,mid,right);
}
private void merge(int[] arr,int left,int mid,int right) {
int start1 = left;
int start2 = mid + 1;
for (int i = left; i <= right; i++) {
T[i] = arr[i];
}
for (int i = left; i <= right; i++) {
if (start1 > mid) arr[i] = T[start2++];
else if (start2 > right) arr[i] = T[start1++];
else if (T[start1] < T[start2]) arr[i] = T[start1++];
else arr[i] = T[start2++];
}
}
二、描述
- 归并排序的核心思想是将两个有序数组合成一个更大的有序数组,首先利用递归将一个大的数组逐步进行切分,直到大数组被切分成一个个很小的子数组。然后将小的数组进行排序,同时进行合并操作。
- 创建一个和排序目标数组长度一样的辅助数组,因为创建足够大的数组,在之后的排序操作时,就不会因为辅助数组不够大而再次创建新的数组,消除了创建数组过程中的时间开销。利用这个辅助数组可以先将前半部分排序,再将后半部分排序,然后在数组中移动元素而不需要额外的空间了。
private int[] T;
private void mergeSort(int[] arr) {
int n = arr.length;
T = new int[n];
sort(arr,0,n - 1);
}
- 利用抽象实现排序并归并,这也是一个高效利用分治思想的典型例子。
private void sort(int[] arr,int left,int right) {
if (left >= right) return;
int mid = left + ((right - left) >> 1);
sort(arr,left,mid);
sort(arr,mid + 1,right);
merge(arr,left,mid,right);
}
- 判断左右边界是否越界,越界了就终止当前方法。将子数组 arr[left...right] 复制到 T[left...right] 中,然后将 arr[left...mid] 和 arr[mid + 1...right] 合并成一个有序子数组并把结果存放到原数组中(arr[left...right])。
private void merge(int[] arr,int left,int mid,int right) {
int start1 = left;
int start2 = mid + 1;
for (int i = left; i <= right; i++) {
T[i] = arr[i];
}
for (int i = left; i <= right; i++) {
if (start1 > mid) arr[i] = T[start2++];
else if (start2 > right) arr[i] = T[start1++];
else if (T[start1] < T[start2]) arr[i] = T[start1++];
else arr[i] = T[start2++];
}
}
三、最后
- 以上内容参考自《算法第四版》。
- 在归并中有自底向上和自顶向下两种方法,具体可以去看一下书,效果可以看一下下面放的图,哈哈哈...呃。