以下是使用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;
}
@Override
protected 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