自然归并排序和单链表实现的归并排序

自然归并排序

(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);
	}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值