【问题标题】:4 threaded merge sort algorithm4线程归并排序算法
【发布时间】:2016-01-25 01:56:23
【问题描述】:

我想将 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);
    }
}

【问题讨论】:

  • “我该如何实现”不是一个合适的问题。您面临的实际问题是什么?
  • 我无法合并已排序的子数组

标签: java multithreading sorting merge


【解决方案1】:

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-21
    • 1970-01-01
    • 2016-04-07
    • 2011-02-22
    • 1970-01-01
    • 2017-07-05
    • 1970-01-01
    相关资源
    最近更新 更多