归并排序
今天带来的依旧是算法作业系列之🐢病排序(🐢:???)
哦说错了,是归并排序,我们老师的课件上也叫合并排序,下面是某度的百科的定义。
定义
归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。归并排序是一种稳定的排序方法。
既然建立在归并操作上,那么什么是🐢病操作呢?
将两个顺序序列合并成一个顺序序列的方法。这就是归并操作了。
分析
既然归并操作是讲两个顺序序列合并成一个顺序序列,那么也就是说,归并排序其实也就是通过不断的进行归并操作,使得序列从局部有序逐渐变为整体有序的一个排序过程。
那么我们就可以想象整个过程了。
给一个序列a,我们先将其不断二分,直到最小,然后将相邻两个序列进行序列之间排序、合并,并复制到a的对应范围内。
从局部有序,一点一点就到整体有序了。
代码
递归
/*
* @Title mergeSort
* @Description 递归归并排序
* @author 滑技工厂
* @Date 2020/3/17
* @param [a, left 左指针, right 右指针]
* @return void
* @throws
*/
public static void mergeSort(int a[], int left, int right) {
if (left < right) {//划分的持续条件
//找到中间指针
int i = (left + right) / 2;
//一个序列分为左右两边,分别进行mergesort,然后还会继续划分,
// 直到形成一个元素一个序列的情况,就可以序列之间排序merge了
mergeSort(a, left, i);
mergeSort(a, i + 1, right);
//序列排序并合并到b,left、i、right来进行划分左右序列
int[] b = new int[right - left + 1];
merge(a, b, left, i, right);
copy(a, b, left, right);
}
}
这里只给出归并排序的思路,至于merge和copy方法详情请见我的GitHub
非递归
public static void mergeSort2(int[] arr) {
if (arr == null || arr.length <= 0)
return;
int width = 1;
while (width < arr.length) {
mergePass(arr, width);
width *= 2;
}
}
private static void mergePass(int[] arr, int width) {
int start = 0;
while (start + 2 * width - 1 < arr.length) {
int mid = start + width - 1;
int end = start + 2 * width - 1;
merge2(arr, start, mid, end);
start = start + 2 * width;
}
//剩余无法构成完整的两组也要进行处理
if (start + width - 1 < arr.length)
merge2(arr, start, start + width - 1, arr.length - 1);
}
private static void merge2(int[] arr, int start, int mid, int end) {
int i = start;
int j = mid + 1;
int[] temp = new int[end - start + 1];
int index = 0;
while (i <= mid && j <= end) {
if (arr[i] <= arr[j])
temp[index++] = arr[i++];
else
temp[index++] = arr[j++];
}
while (i <= mid)
temp[index++] = arr[i++];
while (j <= end)
temp[index++] = arr[j++];
for (int k = start; k <= end; k++)
arr[k] = temp[k - start];
}
不知道为什么这篇阅读量这么少,几天了还是4个,里面还有我反复看的。。。。莫非真是因为这篇是我在交作业日期之后发的????