算法导论之第二章之分治法(Java实现数组排序-合并排序)

import java.util.Arrays;
import java.util.Random;

/**
* Filename: Class3FenZhiFa.java Description:
* 使用分治法排序(将数组进行二分拆解,二分拆完再二分直至不能拆,然后进行排序)
* @author: guzhangyan
* @date: 2018年8月3日 上午11:40:28
*/

public class Class3FenZhiFa {

    public static void main(String[] args) {
        int[] shuZu = new int[1000000];
        Random random = new Random();
        for (int i = 0; i < shuZu.length; i++) {
            shuZu[i] = random.nextInt(1000);
        }

        fenZhiFaSort(shuZu, 0, shuZu.length - 1);
        for (int i = 1; i < shuZu.length; i++) {
            if (shuZu[i] - shuZu[i - 1] < 0) {
                System.out.println(i);
            }
        }
        System.out.println(Arrays.toString(shuZu));
    }

    private static void fenZhiFaSort(int[] shuZu, int start, int end) {
        if (end == start) {
            return;
        }
        // 先拆成两部分进行排序
        fenZhiFaSort(shuZu, start, (start + end) / 2);
        fenZhiFaSort(shuZu, (start + end) / 2 + 1, end);
        int thisNum = 0;
        int startKey = start;
        // 依次取后半部分数值,和前半部分依次比较,因为两部分都是拍过序的,所以真实比较次数很少
        // 后半部分下标为i,前半部分为startKey,如果后半部分的值比前者小,则把后半部分值移到前面,startKey及之后的值依次后移(后移的操作比较占时间,比较操作不多)
        for (int i = (start + end) / 2 + 1; i <= end && startKey < i;) {
            thisNum = shuZu[i];
            if (thisNum < shuZu[startKey]) {
                for (int j = i; j > startKey; j--) {
                    shuZu[j] = shuZu[j - 1];
                }
                shuZu[startKey] = thisNum;
                i++;
                startKey++;
            } else {
                //如果前者小,则不需要动,前者后一个进行比较
                startKey++;
            }
        }
    }
}

排序一百万条数据,合并排序78.137s,冒泡排序1268.768s。

优化合并排序
将合并时候的操作,换个方式排序100w数据时间为200毫秒左右,一亿条数据为13.079s
因为T(n) = 2T(n/2) + n;复杂度是o(n*lgn);
而上一个方式为 T(n) = 2T(n/2) + n*n/2;复杂度为n*n;

/**
     * @param shuZu
     * @param start
     * @param end
     * @author: guzhangyan
     * @version:2018年8月6日 上午9:27:33 与分治法1不一样的是:进行排序时候,是直接排序,而非移动式
     */
    private static void fenZhiFaSort2(int[] shuZu, int start, int end) {
        if (end == start) {
            return;
        }
        if (end - start < 100) {// 当函数长度较短时,还是使用方法一合适
            // 先拆成两部分进行排序
            fenZhiFaSort(shuZu, start, (start + end) / 2);
            fenZhiFaSort(shuZu, (start + end) / 2 + 1, end);
        } else {
            // 先拆成两部分进行排序
            fenZhiFaSort2(shuZu, start, (start + end) / 2);
            fenZhiFaSort2(shuZu, (start + end) / 2 + 1, end);
        }
        int startKey1 = start;
        int startKey2 = (start + end) / 2 + 1;
        int[] newShuZu = new int[end - start + 1];
        int newKey = 0;
        while (true) {
            if (startKey1 > (start + end) / 2 && startKey2 > end) {
                break;
            }
            if (startKey1 > (start + end) / 2) {
                newShuZu[newKey] = shuZu[startKey2];
                startKey2++;
                newKey++;
                continue;
            }
            if (startKey2 > end) {
                newShuZu[newKey] = shuZu[startKey1];
                startKey1++;
                newKey++;
                continue;
            }
            if (shuZu[startKey2] > shuZu[startKey1]) {
                newShuZu[newKey] = shuZu[startKey1];
                startKey1++;
                newKey++;
                continue;
            } else {
                newShuZu[newKey] = shuZu[startKey2];
                startKey2++;
                newKey++;
                continue;
            }
        }
        for (int i = 0; i < newShuZu.length; i++) {
            shuZu[start + i] = newShuZu[i];
        }

    }

猜你喜欢

转载自blog.csdn.net/qq_33321609/article/details/81386061