自然归并排序
(1)思路:
1、找出需要排序数组中的所有有序子数组,将每个子数组的起始下标存在一个辅组数组中,假设为mark[]。
2、将有序字数组两两归并,最后得到有序数组。
3、需要注意被排序数组的长度N<=2的特殊情形。
(2)代码
public class NatureMerge extends Sort {
public static <T extends Comparable<? super T>> int pass(T[] arr, int[] mark) {
int j = 0;
T temp = arr[0];
mark[j++] = 0;
for(int i = 1; i < arr.length; i++) {
if(temp.compareTo(arr[i]) <= 0) temp = arr[i];
else mark[j++] = i;
}
mark[j] = arr.length;
return j;
}
public static <T extends Comparable<? super T>> void natureMerge(T[] arr, T[] aux, int[] mark) {
int max = pass(arr, mark);
for(int sz = 1; sz < max; sz += sz) {
for(int i = 0; i < max - sz; i += sz + sz) {
merge(arr, aux, mark[i], mark[i + sz] - 1, mark[Math.min(i + sz + sz, max)] - 1);
}
}
}
//要检查N<=2时的特殊境况
@SuppressWarnings("unchecked")
public static <T extends Comparable<? super T>> void sort(T[] a) {
int N = a.length;
if(N <= 1) return ;
if(N == 2) if(less(a[1], a[0])) exch(a, 0, 1);
int[] mark = new int[N];
T[] aux = (T[])new Comparable[N];
natureMerge(a, aux, mark);
}
private static <T extends Comparable<? super T>> void merge(T[] a, T[] aux, int lo, int mid, int hi) {
for(int i = lo; i <= hi; i++) {
aux[i] = a[i];
}
int j = lo;
int k = mid + 1;
for(int i = lo; i <= hi; i++) {
if(j > mid) a[i] = aux[k++];
else if(k > hi) a[i] = aux[j++];
else if(less(aux[j], aux[k])) a[i] = aux[j++];
else a[i] = aux[k++];
}
}
protected static <T extends Comparable<? super T>> boolean less(T v, T w) {
return v.compareTo(w) < 0;
}
protected static <T extends Comparable<? super T>> void exch(T[] a, int i, int j) {
T swap = a[i];
a[i] = a[j];
a[j] = swap;
}
}
单链表归并排序
public static <T extends Comparable<? super T>> Node<T> sort(Node<T> list) {
if(list == null || list.next == null) return list;
Turple<Node<T>, Node<T>> t = getTwoLists(list);
Node<T> l = sort(t.e1);
Node<T> r = sort(t.e2);
return merge(l, r);
}
public static <T extends Comparable<? super T>> Node<T> merge(Node<T> left, Node<T> right) {
if(left == null) return right;
if(right == null) return left;
if(less(right.data, left.data)) {
Node<T> temp = left;
left = right;
right = temp;
}
Node<T> lf = left;
Node<T> rg = right;
Node<T> temp = null;
while(lf.next != null) {
if(less(right.data, lf.next.data)) {
while(rg.next != null && less(rg.next.data, lf.next.data)) {
rg = rg.next;
}
temp = right;
right = rg.next;
rg.next = lf.next;
lf.next = temp;
if(right == null) break;
}
lf = lf.next;
}
if(lf.next == null) {
lf.next = right;
}
return left;
}
public static <T extends Comparable<? super T>> Turple<Node<T>, Node<T>> getTwoLists(Node<T> list) {
if(list.next == null) throw new ArrayIndexOutOfBoundsException();
Node<T> p1 = list;
Node<T> p2 = list;
Node<T> temp = null;
while(p2.next != null) {
p2 = p2.next;
if(p2.next != null) {
p2 = p2.next;
}
temp = p1;
p1 = p1.next;
}
temp.next = null;
return new Turple<Node<T>, Node<T>>(list, p1);
}