双线程排序的简单实现

数据量非常大的时候用多线程排序应该会很快的吧,虽然网上有不少多线程排序的例子,但是感觉都很复杂的样子,所以今天我们用最基础的知识写一个最简单的,用的是java语言。
如果使用多线程的话,快速排序应该是最合适的,因为快排是分区进行的(Arrays.sort()中可以找到快速排序的代码)。

我们先利用快排算法把数组分成两部分:

关于快速排序可以参考这个(需要稍作修改以应对数组中有重复元素的情况)
http://www.cnblogs.com/luchen927/archive/2012/02/29/2368070.html

int[] arr = { 5, 3, 7, 4, 8, 9, 55, 44, 33, 22, 11, 11, 4, 5, 6, 7, 3,
                2, 66, 44, 2, 34, 21, 6, 54 };
        int key = arr[0]; // 以第一个数为关键数
        int low = 0;
        int high = arr.length - 1;
        while (low < high) {
            while (low < high && arr[high] >= key) {
                high--;
            }
            arr[low] = arr[high]; // 从后向前遍历,找到小于关键数的元素放到前面
            while (low < high && arr[low] <= key) {
                low++;
            }
            arr[high] = arr[low]; // 从前向后遍历,找到大于关键数的元素放到后边
        }
        arr[low] = key; // 完成本次交换,把关键数插入中间位置,把数组分为两段

这样我们就得到了arr[0]-arr[low-1]和arr[low+1]-arr[arr.length-1]这两个数组区间,接下来我们构造线程分别对他们进行排序(不需要同步),并在每一次分区后输出数组以便使过程更加直观:

class SortThread extends Thread {
    private int left, right;
    private int[] arr;


    SortThread(int[] arr, int left, int right) {
        this.arr = arr;
        this.left = left;
        this.right = right;
    } // run()不带参数,所以用构造方法传入参数


    private void sort(int[] arr, int left, int right) {
        if (left < right) {
            int key = arr[left];
            int low = left;
            int high = right;
            while (low < high) {
                while (low < high && arr[high] >= key) {
                    high--;
                }
                arr[low] = arr[high];
                while (low < high && arr[low] <= key) {
                    low++;
                }
                arr[high] = arr[low];
            }
            arr[low] = key;
            System.out.println(Arrays.toString(arr));
            sort(arr, left, low - 1);
            sort(arr, low + 1, right);
        }
    }  //这一部分跟上面的一样


    @Override
    public void run() {
        sort(arr, left, right); // 调用排序算法
    }
}

现在只要开启两个线程就行了:

SortThread p1 = new SortThread(arr, 0, low - 1); // 对前一段排序
SortThread p2 = new SortThread(arr, low + 1, arr.length - 1); // 对后一段排序
p1.start();
p2.start();

输出结果如下:

[2, 3, 2, 4, 3, 4, 5, 44, 33, 22, 11, 11, 55, 5, 6, 7, 9, 8, 66, 44, 7, 34, 21, 6, 54]
[2, 3, 2, 4, 3, 4, 5, 44, 33, 22, 11, 11, 55, 5, 6, 7, 9, 8, 66, 44, 7, 34, 21, 6, 54]
[2, 2, 3, 4, 3, 4, 5, 44, 33, 22, 11, 11, 55, 5, 6, 7, 9, 8, 66, 44, 7, 34, 21, 6, 54]
[2, 2, 3, 3, 4, 4, 5, 44, 33, 22, 11, 11, 55, 5, 6, 7, 9, 8, 66, 44, 7, 34, 21, 6, 54]
[2, 2, 3, 3, 4, 4, 5, 6, 33, 22, 11, 11, 21, 5, 6, 7, 9, 8, 34, 44, 7, 44, 66, 55, 54]
[2, 2, 3, 3, 4, 4, 5, 5, 6, 22, 11, 11, 21, 33, 6, 7, 9, 8, 34, 44, 7, 44, 66, 55, 54]
[2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 11, 11, 21, 8, 6, 7, 9, 22, 34, 44, 33, 44, 66, 55, 54]
[2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 11, 21, 8, 11, 7, 9, 22, 34, 44, 33, 44, 66, 55, 54]
[2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 9, 7, 8, 11, 11, 21, 22, 34, 44, 33, 44, 66, 55, 54]
[2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 8, 7, 9, 11, 11, 21, 22, 34, 44, 33, 44, 66, 55, 54]
[2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9, 11, 11, 21, 22, 34, 44, 33, 44, 66, 55, 54]
[2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9, 11, 11, 21, 22, 33, 34, 44, 44, 66, 55, 54]
[2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9, 11, 11, 21, 22, 33, 34, 44, 44, 54, 55, 66]
[2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9, 11, 11, 21, 22, 33, 34, 44, 44, 54, 55, 66]

要注意的是,这种代码虽然可以用超大号的样本进行试验,但是一不小心就会溢出呀。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值