/***
* 归并排序(分治思想的典型应用):
*
* 分为自上而下(递归)和自下而上(非递归,比较适合用链表组织的数据)的算法
*
* 特点:
*
* 保证将任意长度为N的数组排序所需的时间和NlogN成正比;
* 处理有百万、千万级别的元素个数的数组不成问题。
*
* 缺点:
*
* 需要的额外空间和N成正比。
*
* 改进方案:
* ①对小规模的子数组使用插入排序
* ②测试数组是否有序
* (加一个判断条件,如果a[mid]小于a[mid+1],我们就认为是有序的,
* 从而跳过merge()方法,这个改动不会影响递归的调用,但是运行时间就变成线性的了。)
*
* 自上而下(递归):
* 将一个大问题分割成小问题分别解决,然后用所有小问题的答案解决大问题的答案。
*
* 自下而上(非递归):
* 先归并那些微型数组,然后再成对归并得到的子数组,直到将整个数组归并到一块。
* (基本思想:首先进行两两归并,把每个元素看成一个大小为1的子数组,
* 然后是四四归并,将两个大小为2的数组归并成一个有4个元素的数组,
* 然后是八八归并,一直下去。)
*/
package com.chapter_two;
/***
* 自顶向下的归并排序
*
* @author LuodiJack
*
*/
public class Merge {
@SuppressWarnings("rawtypes")
private static Comparable[] aux;
/***
* 原地归并的抽象方法: 将两个有序数组归并成更大的有序数组。
*
* @param a
* 需要归并的数组。
* @param low
* 数组的下界,实际的索引值。
* @param mid
* 数组的中部,实际的索引值。
* @param high
* 数组的上界,实际的索引值。
*/
@SuppressWarnings("rawtypes")
private static void merge(Comparable[] a, int low, int mid, int high) {
int i = low;
int j = mid + 1;
for (int k = low; k <= high; k++) {
aux[k] = a[k];
}
for (int k = low; k <= high; k++) {
if (i > mid) {
a[k] = aux[j++];
} else if (j > high) {
a[k] = aux[i++];
} else if (Template.less(aux[i], aux[j])) {
a[k] = aux[i++];
} else {
a[k] = aux[j++];
}
}
}
/***
* 自顶向下的归并排序函数
*
* @param a
* 需要排序的数组
*
*/
@SuppressWarnings("rawtypes")
public static void sort(Comparable[] a) {
aux = new Comparable[a.length];
sort(a, 0, a.length - 1);
}
@SuppressWarnings("rawtypes")
private static void sort(Comparable[] a, int low, int high) {
if (high <= low) {
return;
}
int mid = low + (high - low) / 2;
sort(a, low, mid);
sort(a, mid + 1, high);
merge(a, low, mid, high);
}
}
package com.chapter_two;
/***
* 自底而上的归并排序
*
* @author LuodiJack
*
*/
public class MergeBU {
@SuppressWarnings("rawtypes")
private static Comparable[] aux;
/***
* 原地归并的抽象方法: 将两个有序数组归并成更大的有序数组。
*
* @param a
* 需要归并的数组。
* @param low
* 数组的下界,实际的索引值。
* @param mid
* 数组的中部,实际的索引值。
* @param high
* 数组的上界,实际的索引值。
*/
@SuppressWarnings("rawtypes")
private static void merge(Comparable[] a, int low, int mid, int high) {
int i = low;
int j = mid + 1;
for (int k = low; k <= high; k++) {
aux[k] = a[k];
}
for (int k = low; k <= high; k++) {
if (i > mid) {
a[k] = aux[j++];
} else if (j > high) {
a[k] = aux[i++];
} else if (Template.less(aux[i], aux[j])) {
a[k] = aux[i++];
} else {
a[k] = aux[j++];
}
}
}
/***
* 自底向上的归并排序函数
*
* @param a
* 需要排序的数组
*
*/
@SuppressWarnings("rawtypes")
public static void sort(Comparable[] a) {
int N = a.length;
aux = new Comparable[a.length];
for (int sz = 1; sz < N; sz = sz + sz) {
for (int low = 0; low < N - sz; low += sz + sz) {
merge(a, low, low + sz - 1, Math.min(low + sz + sz - 1, N - 1));
}
}
}
}