java不同场景下的堆排序和归并排序实现

该代码示例展示了使用Java实现的不同排序算法(如堆排序、快速排序、归并排序)对不同数据分布的性能测试。每个测试用例都关注在特定数据规模下,保证在限定的时间内完成排序任务的能力。测试包括随机数、递增、递减、固定间隔等不同数据序列。
摘要由CSDN通过智能技术生成
import java.util.*;
import java.util.stream.IntStream;

public class Test1 {
    static Random random = new Random();

    public static void main(String[] str) {
        //10W量级要求每个案例都小于100ms,100W量级要求每个案例都小于1000ms
        //                test1(100000);
        test1(1000000);
        //10W量级要求每个案例都小于50ms,100W量级要求每个案例都小于400ms
        //        test2(100000);
        test2(1000000);
    }

    public static void test1(int num) {
        System.out.println("TEST1: " + num);

        int cell = 3;

        for (int z = 0; z < 6; z++) {
            short[] tp = new short[num * cell];

            switch (z) {
                case 0:
                    for (int i = 0; i < tp.length; i += cell) {
                        tp[i] = 0;
                        tp[i + 1] = (short) (i / (num / 10));
                        tp[i + 2] = 0;
                    }
                    break;

                case 1:
                    for (int i = 0; i < tp.length; i += cell) {
                        tp[i] = (short) (i >> 2);
                        tp[i + 1] = (short) i;
                        tp[i + 2] = 0;
                    }
                    break;

                case 2:
                    for (int i = 0; i < tp.length; i += cell) {
                        tp[i] = (short) ((tp.length - i) >> 2);
                        tp[i + 1] = (short) (tp.length - i);
                        tp[i + 2] = 0;
                    }
                    break;

                case 3:
                    for (int i = 0; i < tp.length; i += cell) {
                        tp[i] = (short) random.nextInt(30000);
                        tp[i + 1] = (short) random.nextInt(30000);
                        tp[i + 2] = (short) random.nextInt(30000);
                    }
                    break;

                case 4:
                    for (int i = 0; i < tp.length; i += cell) {
                        tp[i] = 0;
                        tp[i + 1] = (short) (1000 - i / (num / 10));
                        tp[i + 2] = 0;
                    }
                    break;

                case 5:
                    for (int i = 0; i < tp.length; i += cell) {
                        tp[i] = 0;
                        tp[i + 1] = 0;
                        tp[i + 2] = (short) random.nextInt(10);
                    }
                    break;

            }

            long t1 = System.currentTimeMillis();

            new SortTest(tp, cell).sort();

            System.out.println("case" + z + " cost " + (System.currentTimeMillis() - t1) + "ms");
        }
    }

    public static void test2(int num) {
        System.out.println("TEST2: " + num);

        for (int z = 0; z < 9; z++) {
            long[] tp = new long[num];

            switch (z) {
                case 0:
                    for (int i = 0; i < tp.length; i++)
                        tp[i] = random.nextInt(num);
                    break;

                case 1:
                    for (int i = 0; i < tp.length; i++)
                        tp[i] = i;
                    break;

                case 2:
                    for (int i = 0; i < tp.length; i++)
                        tp[i] = tp.length - i;
                    break;

                case 3:
                    for (int i = 0; i < tp.length; i++)
                        tp[i] = i / (num / 10);
                    break;

                case 4:
                    for (int i = 0; i < tp.length; i++)
                        tp[i] = 1000 - i / (num / 10);
                    break;

                case 5:
                    for (int i = 0; i < tp.length; i++)
                        tp[i] = i == num / 2 ? 2 : 1;
                    break;

                case 6:
                    for (int i = 0; i < tp.length; i++)
                        tp[i] = random.nextInt(10);
                    break;

                case 7:
                    for (int i = 0; i < tp.length; i++)
                        tp[i] = random.nextInt(100);
                    break;

                case 8:
                    for (int i = 0; i < tp.length; i++)
                        tp[i] = random.nextInt(1000);
                    break;
            }
            long t1 = System.currentTimeMillis();
            //            Arrays.sort(tp); //自带的速度很快,但不满足要求,需求是排下标,而不是排本体
            new MergeSort(tp).sort();//可达到要求
            //            sortByComparator(tp); // case0 600ms左右 其余达标
            //            intStreamSort(tp); // case0 450ms 左右 其余达标
            //            new SortTest2(tp).sort();
            System.out.println("case" + z + " cost " + (System.currentTimeMillis() - t1) + "ms");
        }
    }

    /**
     * TEST2: 1000000
     * case0 cost 429ms
     * case1 cost 34ms
     * case2 cost 14ms
     * case3 cost 71ms
     * case4 cost 9ms
     * case5 cost 76ms
     * case6 cost 86ms
     * case7 cost 103ms
     * case8 cost 138ms
     * @param tp
     */
    private static void intStreamSort(long[] tp) {
        int[] sortedIndices = IntStream.range(0, tp.length).boxed().sorted((i, j) -> {
            if (tp[i] < tp[j])
                return -1;
            if (tp[i] > tp[j])
                return 1;
            return 0;
        }).mapToInt(ele -> ele).toArray();
    }

    /**
     * TEST2: 1000000
     * case0 cost 564ms
     * case1 cost 31ms
     * case2 cost 11ms
     * case3 cost 5ms
     * case4 cost 7ms
     * case5 cost 4ms
     * case6 cost 125ms
     * case7 cost 137ms
     * case8 cost 207ms
     * 使用比较器
     * @param tp
     */
    private static void sortByComparator(long[] tp) {
        ArrayIndexComparator comparator = new ArrayIndexComparator(tp);
        Integer[] indexes = comparator.createIndexArray();
        Arrays.sort(indexes, comparator);
    }

    public static <T extends Object> List<T[]> splitArray(T[] array, int splitSize) {

        int numberOfArrays = array.length / splitSize;
        int remainder = array.length % splitSize;

        int start = 0;
        int end = 0;

        List<T[]> list = new ArrayList<T[]>();
        for (int i = 0; i < numberOfArrays; i++) {
            end += splitSize;
            list.add(Arrays.copyOfRange(array, start, end));
            start = end;
        }

        if (remainder > 0) {
            list.add(Arrays.copyOfRange(array, start, (start + remainder)));
        }
        return list;
    }

    static class SortTest {
        int     cell;

        short[] tp;  //把这个排序,每cell个一组

        public SortTest(short[] tp, int cell) {
            this.cell = cell;
            this.tp = tp;
        }

        void sort() {
            //            System.out.println(JSON.toJSONString(tp));
            int sort = tp.length / cell;
            heapSort(sort);
            //            System.out.println(JSON.toJSONString(tp));
        }

        public void heapSort(int size) {
            int lengthOfArray = size;
            // 创建堆
            for (int i = (lengthOfArray - 1) / 2; i >= 0; i--) {
                heapify(lengthOfArray, i);
            }
            // 排序
            for (int i = lengthOfArray - 1; i >= 0; i--) {
                // Swap the root node with last node
                swap(i, 0);
                heapify(i, 0);
            }
        }

        public void heapify(int index, int i) {
            // 初始化
            int parentIndex = i;
            int leftChild = (2 * i) + 1;
            int rightChild = (2 * i) + 2;
            // 比较左子值
            if (leftChild < index && compare(leftChild, parentIndex) > 0) {
                parentIndex = leftChild;
            }
            // 比较右子值
            if (rightChild < index && compare(rightChild, parentIndex) > 0) {
                parentIndex = rightChild;
            }
            if (parentIndex != i) {
                swap(parentIndex, i);
                heapify(index, parentIndex); // 递归调用
            }
        }

        public void sort(int size) {
            int index;
            for (int i = 1; i < size + 1; i++) {
                index = 0;
                for (int j = 1; j <= size + 1 - i; j++) {
                    if (compare(j, index) >= 0) {
                        index = j;
                    }
                }
                //交换在位置array.length - i 和 index(最大值)上的两个元素
                swap(size - i, index);
            }
        }

        void swap(int p1, int p2) {
            int i1 = p1 * cell;
            int i2 = p2 * cell;

            short s1 = tp[i1];
            short s2 = tp[i1 + 1];
            short s3 = tp[i1 + 2];

            tp[i1] = tp[i2];
            tp[i1 + 1] = tp[i2 + 1];
            tp[i1 + 2] = tp[i2 + 2];

            tp[i2] = s1;
            tp[i2 + 1] = s2;
            tp[i2 + 2] = s3;
        }

        int compare(int p1, int p2) {
            int i1 = p1 * cell;
            int i2 = p2 * cell;

            long v1 = (long) (tp[i1] << 4) | (tp[i1 + 1] << 2) | tp[i1 + 2];
            long v2 = (long) (tp[i2] << 4) | (tp[i2 + 1] << 2) | tp[i2 + 2];

            return v1 == v2 ? 0 : v1 > v2 ? -1 : 1;
        }
    }

    static class SortTest2 {
        long[]            vals;

        int[]             indexes;                  //vals的下标位置,排序排这个,vals不要动,最终 vals[indexes[0]], vals[indexes[1]] ... vals[indexes[n]] 是有序的

        int               size;
        LinkedList<int[]> list = new LinkedList<>();

        public SortTest2(long[] vals) {
            this.vals = vals;
            this.size = vals.length;

            indexes = new int[size];
            for (int i = 0; i < size; ++i) //初始时,下标是0...n的次序
                indexes[i] = i;
        }

        public void sort() {
            list.add(new int[] { 0, size - 1 });

            while (!list.isEmpty()) {
                int[] n = list.removeLast();
                int[] r = quickPos2(n[0], n[1]);
                if (r[2] < r[3])
                    list.add(new int[] { r[2], r[3] });
                if (r[0] < r[1])
                    list.add(new int[] { r[0], r[1] });
            }
        }

        private int[] quickPos2(int low, int high) {
            int p = random.nextInt(high - low);
            if (p > 0)
                swap(low, low + p);

            int i = low;
            int j = high;
            int b = indexes[low];
            long c = vals[b];

            while (i < j) {
                while (c <= vals[indexes[j]] && i < j)
                    j--;
                while (c >= vals[indexes[i]] && i < j)
                    i++;
                if (i < j)
                    swap(i, j);
            }

            indexes[low] = indexes[i];
            indexes[i] = b;

            return new int[] { low, j - 1, j + 1, high };
        }

        private void swap(int x, int y) {
            int n = indexes[x];
            indexes[x] = indexes[y];
            indexes[y] = n;
        }
    }

    static class ArrayIndexComparator implements Comparator<Integer> {
        private final long[] array;

        public ArrayIndexComparator(long[] array) {
            this.array = array;
        }

        public Integer[] createIndexArray() {
            Integer[] indexes = new Integer[array.length];
            for (int i = 0; i < array.length; i++) {
                indexes[i] = i;
            }
            return indexes;
        }

        @Override
        public int compare(Integer index1, Integer index2) {
            if (array[index1] < array[index2])
                return -1;
            if (array[index1] > array[index2])
                return 1;
            return 0;
        }
    }

    /**
     * TEST2: 1000000
     * case0 cost 261ms
     * case1 cost 182ms
     * case2 cost 153ms
     * case3 cost 203ms
     * case4 cost 134ms
     * case5 cost 106ms
     * case6 cost 237ms
     * case7 cost 183ms
     * case8 cost 152ms
     */
    static class MergeSort {
        private long[] array;     //原数组
        private long[] arraySort; //排序数组
        private long[] indexes;   //数组下标
        private int    start;     //排序开始位
        private int    end;       //排序结束位

        public MergeSort(long[] array) {
            int size = array.length;
            start = 0;
            end = size - 1;
            indexes = new long[size];
            arraySort = Arrays.copyOf(array, array.length);
            for (int i = 0; i < size; ++i) //初始时,下标是0...n的次序
                indexes[i] = i;
        }

        public void sort() {
            //            System.out.println(JSON.toJSONString(arraySort));
            this.sortRecursion(arraySort, indexes, start, end);
            //            System.out.println(JSON.toJSONString(arraySort));
            //            System.out.println(JSON.toJSONString(indexes));
        }

        private void sortRecursion(long[] arraySort, long[] indexes, int start, int end) {
            if (start >= end)
                return;
            int middle = (end - start) / 2 + start;
            sortRecursion(arraySort, indexes, start, middle);
            sortRecursion(arraySort, indexes, middle + 1, end);
            merge(arraySort, indexes, start, middle, end);
        }

        private void merge(long[] array, long[] indexes, int start, int middle, int end) {
            int len1 = middle - start + 1;
            int len2 = end - middle;
            long leftArray[] = new long[len1];
            long leftIndex[] = new long[len1];
            long rightArray[] = new long[len2];
            long rightIndex[] = new long[len2];
            for (int i = 0; i < len1; ++i)
                leftArray[i] = array[i + start];
            for (int i = 0; i < len1; ++i)
                leftIndex[i] = indexes[i + start];
            for (int i = 0; i < len2; ++i)
                rightArray[i] = array[i + middle + 1];
            for (int i = 0; i < len2; ++i)
                rightIndex[i] = indexes[i + middle + 1];
            //merge
            int i = 0, j = 0, k = start;
            while (i < len1 && j < len2) {
                if (leftArray[i] < rightArray[j]) {
                    array[k] = leftArray[i];
                    indexes[k] = leftIndex[i];
                    ++i;
                } else {
                    array[k] = rightArray[j];
                    indexes[k] = rightIndex[j];
                    ++j;
                }
                ++k;
            }
            while (i < len1) {
                array[k] = leftArray[i];
                indexes[k] = leftIndex[i];
                ++i;
                ++k;
            }
            while (j < len2) {
                array[k] = rightArray[j];
                indexes[k] = rightIndex[j];
                ++j;
                ++k;
            }
        }
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值