以下是使用Java的自上而下合并排序算法的典型实现:
import java.lang.reflect.Array;public class MergeSort {public static <T extends Comparable<? super T>> void sort(T[] a) {@SuppressWarnings('unchecked')T[] helper = (T[])Array.newInstance(a[0].getClass() , a.length);mergesort(a, helper, 0, a.length-1);}private static <T extends Comparable<? super T>> void mergesort(T[] a, T[] helper, int lo, int hi){if (lo>=hi) return;int mid = lo + (hi-lo)/2;mergesort(a, helper, lo, mid);mergesort(a, helper, mid+1, hi);merge(a, helper, lo, mid, hi); }private static <T extends Comparable<? super T>> void merge(T[] a, T[] helper, int lo, int mid, int hi){for (int i=lo;i<=hi;i++){helper[i]=a[i];}int i=lo,j=mid+1;for(int k=lo;k<=hi;k++){if (i>mid){a[k]=helper[j++];}else if (j>hi){a[k]=helper[i++];}else if(isLess(helper[i], helper[j])){a[k]=helper[i++];}else{a[k]=helper[j++];}}}private static <T extends Comparable<? super T>> boolean isLess(T a, T b) {return a.compareTo(b) < 0;}
}
为了快速描述算法-
递归执行以下步骤:
- 输入数据分为两半
- 每一半都被排序
- 然后将排序的数据合并
合并排序是使用Java Fork / Join池实现的一个典型示例 ,以下是使用Fork / Join框架的合并排序的盲目实现:
合并排序中的递归任务可以简单地表示为RecursiveAction的实现–
private static class MergeSortTask<T extends Comparable<? super T>> extends RecursiveAction{private static final long serialVersionUID = -749935388568367268L;private final T[] a;private final T[] helper;private final int lo;private final int hi;public MergeSortTask(T[] a, T[] helper, int lo, int hi){this.a = a;this.helper = helper;this.lo = lo;this.hi = hi;}@Overrideprotected void compute() {if (lo>=hi) return;int mid = lo + (hi-lo)/2;MergeSortTask<T> left = new MergeSortTask<>(a, helper, lo, mid);MergeSortTask<T> right = new MergeSortTask<>(a, helper, mid+1, hi);invokeAll(left, right);merge(this.a, this.helper, this.lo, mid, this.hi);}private void merge(T[] a, T[] helper, int lo, int mid, int hi){for (int i=lo;i<=hi;i++){helper[i]=a[i];}int i=lo,j=mid+1;for(int k=lo;k<=hi;k++){if (i>mid){a[k]=helper[j++];}else if (j>hi){a[k]=helper[i++];}else if(isLess(helper[i], helper[j])){a[k]=helper[i++];}else{a[k]=helper[j++];}}}private boolean isLess(T a, T b) {return a.compareTo(b) < 0;}}
上面的MergeSortTask实现了一个计算方法,该方法接受一个值数组,将其拆分为两个部分,从每个部分中创建一个MergeSortTask并分叉另外两个任务(因此称为RecursiveAction!)。 此处用于生成任务的特定API是invokeAll ,仅当已提交的子任务标记为已完成时才返回。 因此,左右子任务返回后,结果将合并到合并例程中。
鉴于此,剩下的唯一工作就是使用ForkJoinPool提交此任务。 ForkJoinPool与用于在线程池中分发任务的ExecutorService类似,不同之处在于引用了ForkJoinPool的API文档:
ForkJoinPool与其他类型的ExecutorService的不同之处主要在于采用了工作窃取:池中的所有线程都试图查找并执行由其他活动任务创建的子任务(如果不存在,则最终阻塞等待工作)
这是将任务提交到Fork / Join Pool的任务的样子:
public static <T extends Comparable<? super T>> void sort(T[] a) {@SuppressWarnings('unchecked')T[] helper = (T[])Array.newInstance(a[0].getClass() , a.length);ForkJoinPool forkJoinPool = new ForkJoinPool(10);forkJoinPool.invoke(new MergeSortTask<T>(a, helper, 0, a.length-1));}
完整的示例也可以在这里找到: https : //github.com/bijukunjummen/algos/blob/master/src/main/java/org/bk/algo/sort/algo04/merge/MergeSortForkJoin.java
参考: all和其他博客中的Mergesort 使用我们JCG合作伙伴 Biju Kunjummen的Fork / Join Framework 。
翻译自: https://www.javacodegeeks.com/2012/08/java-mergesort-using-forkjoin-framework.html