“归并”是将两个或两个以上的有序表组合成一个新的有序表。假定待排序表含有n个记录,则可以看成是n个
有序的子表,每个子表的长度为1,然后两两归并,得到n/2个长度为12或1的有序表;再两两归并,...如此重复,
直到合并成一个长度为n的有序表为止。这种排序方法称为2-路归并排序。
归并排序: (基于分治法)
public void mergeSort(int[] a, int left, int right)
{
if (left < right) // 至少有两个元素
{
int middle = (left + right) / 2; // 从中间划分出两个子序列
mergeSort(a, left, middle); // 对左侧子序列进行递归排序
mergeSort(a, middle+1, right); // 对右侧子序列进行递归排序
merge(a, left, middle, right); // 将左右两个子序列合并
}
}
private void merge(int[] a, int left, int middle, int right)
{
int[] tmpArray = new int[a.length]; // 创建一个临时数组,存放合并的数组
int rightStart = middle + 1;
int tmp = left;
int third = left; // 合并后新数组的起始下标
// 比较两个数组( [left,middle]和[middle+1, right] )中相应下标位置的元素大小,小的元素先放入新数组
while (left <= middle && rightStart <= right)
{
if (a[left] <= a[rightStart])
{
tmpArray[third++] = a[left++];
}
else
{
tmpArray[third++] = a[rightStart++];
}
}
// 如果左边数组还有元素,就把剩余的元素拷贝到新数组中
while (left <= middle)
{
tmpArray[third++] = a[left++];
}
// 如果右边数组还有元素,就把剩余的元素拷贝到新数组中
while (rightStart <= right)
{
tmpArray[third++] = a[rightStart++];
}
System.out.println("临时数组tmpArray:" + Arrays.toString(tmpArray));
while (tmp <= right)
{
a[tmp] = tmpArray[tmp]; // 拷贝合并后的数组到原数组中
tmp++;
}
}
2-路归并排序算法:
空间效率:merge()操作中,辅助空间的大小为n,所以空间复杂度为O(n)。
时间效率:每一趟归并排序的时间复杂度是O(n),共需要进行log2n归并,时间复杂度为O(nlog2n)。
稳定性:2-路归并排序算法是一个稳定的排序算法。