奇偶排序及其并行化设计

2018-10-19  本文已影响0人  囧略囧

题目

奇偶排序及其并行化设计

定义

奇偶排序法的思路是在数组中重复两趟扫描。第一趟扫描选择所有的数据项对,a[j]和a[j+1],j是奇数(j=1, 3, 5……)。如果它们的关键字的值次序颠倒,就交换它们。第二趟扫描对所有的偶数数据项进行同样的操作(j=0,2, 4,6……)。重复进行这样两趟的排序直到数组全部有序。

奇偶交换总是成对出现,这样才能保证比较和交换涉及到数组中的每一个元素。

分析

奇偶排序可以看做是冒泡排序的升级版,但冒泡排序中每个元素既可能与前面的元素交换,也可能与后面的元素交换,奇偶排序消除了这种数据的相关性,所以可以实现并行化设计。

串行算法

public class Solution {
   public void oddEvenSort(int[] array) {
       int start = 1;
       boolean swap = true;
       while (!(swap == false && start == 1)) {
           swap = false;
           for(int i = start; i < array.length - 1; i += 2) {
               if(array[i] > array[i + 1]) {
                   int tmp = array[i];
                   array[i] = array[i + 1];
                   array[i + 1] = tmp;
                   swap = true;
               }
           }
           if (start == 1) {
               start = 0;
           } else {
               start =1;
           }
       }
   }
}

只有在没有发生交换且完成了一对奇偶交换时才代表数组已经有序,可以退出循环。这里由于是从奇交换开始的,所以只有完成了偶交换且没有交换发生才能退出循环。使用swap记录是否有交换发生,使用start值的变化实现奇偶交换的交替。初始时start为1,进行奇交换,之后变为0,进行偶交换。

并行算法

public class Solution {
    static int[] array = {1, 4, 5, 2, 3};
    static boolean swap;
    static ExecutorService es = Executors.newCachedThreadPool();

    public Solution(int[] a ) {
        this.array = a;
    }

    public static synchronized void setSwap (boolean s) {
        swap = s;
    }

    public static synchronized boolean getSwap() {
        return swap;
    }

    public static class oddEvenSort implements Runnable {
        int i;
        CountDownLatch latch;
        public oddEvenSort(int i, CountDownLatch latch) {
            this.i = i;
            this.latch = latch;
        }

        @Override
        public void run() {
            if(array[i] > array[i + 1]) {
                int tmp = array[i];
                array[i] = array[i + 1];
                array[i + 1] = tmp;
                setSwap(true);
            }
            latch.countDown();
        }
    }

    public static void main(String[] args) throws InterruptedException{
        setSwap(true);
        int start = 1;
        while (!(getSwap() == false && start == 1)) {
            setSwap(false);
            CountDownLatch latch = new CountDownLatch((array.length - start) / 2);
            //或  CountDownLatch latch = new CountDownLatch(array.length/2 -(array.length%2 == 0?start:0));
            for(int i = start; i < array.length - 1; i += 2) {
                es.submit(new oddEvenSort(i, latch));
            }
            latch.await();
            if(start == 0) {
                start = 1;
            } else {
                start = 0;
            }
        }
        System.out.println(Arrays.toString(array));
        es.shutdown();
    }
}

通过CountDownLatch记录线程数量,在下一次迭代前必须完成所有线程的排序。

上一篇 下一篇

猜你喜欢

热点阅读