4线程合并排序算法

时间:2016-01-25 01:56:24

标签: java multithreading sorting merge

我想将2线程合并排序修改为4线程合并排序。首先,我想将数组划分为4个相等的子数组(最后一个子数组可能更大)并将它们分配到单独的线程中进行排序。最后,合并1和2子阵列以及3和4个子阵列,然后合并已经排序合并的1和2子阵列以及已合并的3和4子阵列。 这就是我现在所拥有的:
我该如何实现呢?非常感谢!!!

package four_threaded;
import java.util.Random;

public class four_threaded_merge_sort {

    public static void finalMerge(int[] a, int[] b) {
        int[] result = new int[a.length + b.length];
        int i=0; 
        int j=0; 
        int r=0;
        while (i < a.length && j < b.length) {
            if (a[i] <= b[j]) {
                result[r]=a[i];
                i++;
                r++;
            }
            else {
                result[r]=b[j];
                j++;
                r++;
            }
            if (i==a.length) {
                while (j<b.length) {
                    result[r]=b[j];
                    r++;
                    j++;
                }
            }
            if (j==b.length) {
                while (i<a.length) {
                    result[r]=a[i];
                    r++;
                    i++;
                }
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Random rand = new Random();
        int[] original = new int[10];
        for (int i=0; i<original.length; i++) {
            original[i] = rand.nextInt(100);
        }

        long startTime = System.currentTimeMillis();

        int s = original.length / 4 ;
        int r = original.length % 4;

        //first subarray
        int[] subArr1 = new int[s];
        System.arraycopy(original, 0, subArr1, 0, s);
        //second subarray
        int[] subArr2 = new int[s];
        System.arraycopy(original, s, subArr2, 0, s);
        //third subarray
        int[] subArr3 = new int[s];
        System.arraycopy(original, 2*s, subArr3, 0, s);
        //fourth subarray
        int[] subArr4 = new int[s+r];
        System.arraycopy(original, 3*s, subArr4, 0, s+r);

        Worker runner1 = new Worker(subArr1);
        Worker runner2 = new Worker(subArr2);
        Worker runner3 = new Worker(subArr3);
        Worker runner4 = new Worker(subArr4);
        runner1.start();
        runner2.start();
        runner3.start();
        runner4.start();
        runner1.join();
        runner2.join();
        runner3.join();
        runner4.join();

        finalMerge(runner1.getInternal(), runner2.getInternal());


        long stopTime = System.currentTimeMillis();
        long elapsedTime = stopTime - startTime;
        System.out.println("4-thread MergeSort takes: " + (float)elapsedTime/1000 + " seconds"); 

    }

}

class Worker extends Thread {
    private int[] internal;

    public int[] getInternal() {
        return internal;
    }

    public void mergeSort(int[] array) {
        if (array.length > 1) {
            int[] left = leftHalf(array);
            int[] right = rightHalf(array);

            mergeSort(left);
            mergeSort(right);

            merge(array, left, right);
        }
    }

    public int[] leftHalf(int[] array) {
        int size1 = array.length / 2;
        int[] left = new int[size1];
        for (int i = 0; i < size1; i++) {
            left[i] = array[i];
        }
        return left;
    }

    public int[] rightHalf(int[] array) {
        int size1 = array.length / 2;
        int size2 = array.length - size1;
        int[] right = new int[size2];
        for (int i = 0; i < size2; i++) {
            right[i] = array[i + size1];
        }
        return right;
    }

    public void merge(int[] result, int[] left, int[] right) {
        int i1 = 0;   
        int i2 = 0;   

        for (int i = 0; i < result.length; i++) {
            if (i2 >= right.length || (i1 < left.length && left[i1] <= right[i2])) {
                result[i] = left[i1];   
                i1++;
            } else {
                result[i] = right[i2];   
                i2++;
            }
        }
    }

    Worker(int[] arr) {
        internal = arr;
    }

    public void run() {
        mergeSort(internal);
    }
}

1 个答案:

答案 0 :(得分:0)

4个线程完成后,您可以使用2个线程将4个子阵列合并为2个子阵列,尽管这可能没什么用,因为大型阵列的合并将限制内存带宽。您还可以使用主线程进行4路合并。在具有16个寄存器的处理器上,如64位模式的PC,有足够的寄存器通过指针或索引处理4个子阵列。

如果速度是此处的目标,那么分配一个工作数组并使用自下而上的合并排序将比自上而下更快。为避免复制,每个合并排序交替合并原始数据和工作数组之间的数据。每个合并排序可以确定所需的传递次数,如果它是一个奇数,则交换第一次传递而不是合并到另一个缓冲区。

如果最终传递将是4路合并,那么每个合并排序线程应该以工作数组中的排序数据结束。在这种情况下,如果它是偶数次传球,那么就换掉第一次传球。您可能希望一次进行超过2个元素的就地交换。使用类似排序网络的东西,可以使用6个if / swap语句交换4个元素。我不确定使用其他就地排序方法来帮助小组元素。