归并排序主要是两大模块 分治 和 合并
即将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并 由于使用了新的数组 那么空间复杂度就为O(n) 但这一排序会相同数据的位置保持不变即 保持数组的稳定性
以[8, 4, 5, 7, 1, 3, 6, 2]为例
执行的顺序为
mergeSort(A, 0, 7) // 处理整个数组
├── mergeSort(A, 0, 3) // 处理左半部分
│ ├── mergeSort(A, 0, 1) // 处理 [8, 4]
│ │ ├── mergeSort(A, 0, 0) // 处理 [8](终止)
│ │ ├── mergeSort(A, 1, 1) // 处理 [4](终止)
│ │ ├── merge(A, 0, 1, temp) // 合并 [8] 和 [4]
│ ├── mergeSort(A, 2, 3) // 处理 [5, 7]
│ │ ├── mergeSort(A, 2, 2) // 处理 [5](终止)
│ │ ├── mergeSort(A, 3, 3) // 处理 [7](终止)
│ │ ├── merge(A, 2, 3, temp) // 合并 [5] 和 [7]
│ ├── merge(A, 0, 3, temp) // 合并 [4, 8] 和 [5, 7]
├── mergeSort(A, 4, 7) // 处理右半部分
│ ├── mergeSort(A, 4, 5) // 处理 [1, 3]
│ │ ├── mergeSort(A, 4, 4) // 处理 [1](终止)
│ │ ├── mergeSort(A, 5, 5) // 处理 [3](终止)
│ │ ├── merge(A, 4, 5, temp) // 合并 [1] 和 [3]
│ ├── mergeSort(A, 6, 7) // 处理 [6, 2]
│ │ ├── mergeSort(A, 6, 6) // 处理 [6](终止)
│ │ ├── mergeSort(A, 7, 7) // 处理 [2](终止)
│ │ ├── merge(A, 6, 7, temp) // 合并 [6] 和 [2]
│ ├── merge(A, 4, 7, temp) // 合并 [1, 3] 和 [2, 6]
├── merge(A, 0, 7, temp) // 合并 [4, 5, 7, 8] 和 [1, 2, 3, 6]
关键点在于
mergeSort() 先递归拆分,直到 start == end(单个元素),然后回溯时合并。
merge() 只在两个子数组都已经排序后才会执行。
merge() 总是在 mergeSort() 递归调用之后执行,保证子数组是有序的再进行合并
类似于二叉树的后续遍历 即左右根
[8, 4, 5, 7, 1, 3, 6, 2]
/ \
[8, 4, 5, 7] [1, 3, 6, 2]
/ \ / \
[8, 4] [5, 7] [1, 3] [6, 2]
/ \ / \ / \ / \
[8] [4] [5] [7] [1] [3] [6] [2]
下面为实现的代码
public class Solution {
public void sortIntegers2(int[] A) {
if(A==null||A.length<=0)
{
return;
}
int[] temp=new int[A.length];
mergeSort(A,0,A.length-1,temp);
}
void mergeSort(int[] A,int start,int end,int[] temp)
{
if(start>=end)
{
return;
}
int mid=(start+end)/2;
//递归将其分治 将所有的数字最终分解为一个元素
mergeSort(A,start,mid,temp);
mergeSort(A,mid+1,end,temp);
//递归完成后进行合并已排好序的数组
merge(A,start,end,temp);
}
void merge(int[] A,int start,int end,int[] temp)
{
int middle = (start + end) / 2;
int leftIndex=start;
int rightIndex=middle+1;
int Index=start;
//比较两个左右子数列 按照从小打大的顺序进行排序
while(leftIndex<=middle&&rightIndex<=end)
{
if(A[leftIndex]<=A[rightIndex])
{
temp[Index++]=A[leftIndex++];
}else
{
temp[Index++]=A[rightIndex++];
}
}
//将余下的左子序列赋值至剩余的temp数组中
while(leftIndex<=middle)
{
temp[Index++]=A[leftIndex++];
}
//将余下的右子序列赋值至剩余的temp数组中
while(rightIndex<=end)
{
temp[Index++]=A[rightIndex++];
}
for(int i=start;i<=end;i++)
{
A[i]=temp[i];
}
}
}