11种排序算法的简单实鉴和简单性能测试

最近看算法导论,前面说了几种排序算法,于是我就都实践了一把,并且写了个简单的程序测试他们的正确性和性能,看能否和理论对的上,虽然我考虑到系统调度等因素实验其实并不是很严谨,主要是作为娱乐吧哈哈哈哈。本次排序算法包括

-1选择排序 n2

-2冒泡排序 n2

-3插入排序 n2

-4归并排序 nlgn

-5堆排序 nlgn

-6快速排序 nlgn

-7桶排序 n

-8计数排序 n

-9基数排序 n

-10摆烂排序 1

-11希尔排序 n(1.X)

(由于二分查找的插入排序每次其实也需要移动o(n)次,只是减少了对比的次数,时间复杂性没有变化,本次就不考虑它了)

首先先看代码

1 选择排序:

public class SelectSorter implements Sorter {
    @Override
    public void sort(int[] nums) {
        int len = nums.length;
        for(int i = 0; i < len; i ++){
            for(int j = i + 1; j < len; j ++){
                if(nums[i] > nums[j]){
                    ArrayUtil.swap(nums, i, j);
                }
            }
        }
    }
}

2冒泡排序

public class BubbleSorter implements Sorter {
    @Override
    public void sort(int[] nums) {
        int end = nums.length - 1;
        boolean finish;
        for(int i = end; end > 0; end --){
            finish = true;
            for(int j = 0; j < end; j ++){
                int next = j + 1;
                if(nums[j] > nums[next]){
                    ArrayUtil.swap(nums, j, next);
                    finish = false;
                }
            }

            if(finish){
                return;
            }

        }
    }
}

3插入排序

public class InsertSorter implements Sorter {
    @Override
    public void sort(int[] nums) {
        int len = nums.length;
        for(int i = 1; i < len; i ++){
            int value = nums[i];
            int index = i - 1;
            while(index >= 0 && value < nums[index]){
                nums[index + 1] = nums[index];
                index --;
            }
            nums[index + 1] = value;
        }

    }
}

4归并排序

public class MergeSorter implements Sorter {
    @Override
    public void sort(int[] nums) {
        mergeSort(nums, 0, nums.length);
    }

    private void mergeSort(int[] nums, int start, int end){
        if(start + 1 < end){
            int n = end - start;
            int mid = start + n / 2;
            mergeSort(nums, start, mid);
            mergeSort(nums, mid, end);
            mergeSegment(nums, start, mid, end);
        }
    }

    private void mergeSegment(int[] nums, int start, int border, int end){
        int[] sub1 = Arrays.copyOfRange(nums, start, border);
        int[] sub2 = Arrays.copyOfRange(nums, border, end);
        int index = start, index1 = 0, index2 = 0;
        int sub1Len = sub1.length, sub2Len = sub2.length;
        while (index < end) {
            if (index1 >= sub1Len) {
                nums[index] = sub2[index2];
                index2++;
            } else if (index2 >= sub2Len) {
                nums[index] = sub1[index1];
                index1++;
            } else {
                if (sub1[index1] > sub2[index2]) {
                    nums[index] = sub2[index2];
                    index2++;
                } else {
                    nums[index] = sub1[index1];
                    index1++;
                }
            }
            index++;
        }
    }
}

5堆排序

public class HeapSorter implements Sorter {
    @Override
    public void sort(int[] nums) {
        //根据当前数据建为最大堆
        buildHeap(nums);
        //将最大堆数组转化为排序数组  n * lgn
        headArrayToSortArray(nums, nums.length - 1);

    }

    /**
     * 获取左结点的索引
     */
    private int indexOfLeft(int i){
        //注意 加减优先级比左移高
        return (i << 1) + 1;
    }

    /**
     * 获取右结点的索引
     */
    private int indexOfRight(int i){
        return (i << 1) + 2;
    }

    /**
     * 获取父结点的索引
     */
    private int indexOfParent(int i){
        return (i - 1) >> 1;
    }

    /**
     * 获取堆数组的高
     */
    private int high(int[] heapArray){
        int high = 0;
        int len = heapArray.length;
        while(len > 0){
            high ++;
            len = len >> 1;
        }

        return high;
    }

    /**
     * 对堆的指定位置进行局部调整,调整后他的左子结点和右子结点小于当前结点值,并且往下递归调整
     */
    private void downAdjustHead(int[] headArray, int visibleLen, int index){
        //获取当前值
        int value = headArray[index];
        //存储转移的索引
        int nextIndex = index;
        //存储当前值,左结点,右结点的最大值
        int maxValue = value;
        //获取左结点,右结点的最大值
        int leftIndex = indexOfLeft(index), rightIndex = indexOfRight(index);
        //判断左结点的值是否比当前大,是的话准备往左结点跳转
        if(leftIndex < visibleLen && headArray[leftIndex] > maxValue){
            nextIndex = leftIndex;
            maxValue = headArray[leftIndex];
        }
        //判断右结点的值是否是否比左结点和当前值都大,是的话准备往右结点跳转
        if(rightIndex < visibleLen && headArray[rightIndex] > maxValue){
            nextIndex = rightIndex;
        }

        //如果准备跳转到的索引不是当前索引,进行跳转,并且递归执行
        if(nextIndex != index){
            ArrayUtil.swap(headArray, index, nextIndex);
            downAdjustHead(headArray, visibleLen, nextIndex);
        }

    }

    /**
     * 建堆
     */
    private void buildHeap(int[] headArray){
        int visibleLen = headArray.length;
        int high = high(headArray);
        int maxNonLeafIndex = (1 << (high - 1)) - 2;

        for(int i = maxNonLeafIndex; i >= 0; i --){
            downAdjustHead(headArray, visibleLen, i);
        }
    }

    private void headArrayToSortArray(int[] headArray, int endIndex){
        int i = endIndex;
        while(i > 0){
            ArrayUtil.swap(headArray,0, i);
            i--;
            int visibleLen = i + 1;
            downAdjustHead(headArray, visibleLen, 0);
        }

    }
}

6快速排序

public class QuickSorter implements Sorter {
    @Override
    public void sort(int[] nums) {
        quickSort(nums, 0, nums.length);

    }

    /**
     * 快速排序,输入数组和他的边界(左开右闭),分组快排后返回其边界索引i,把数组分为[left, i) 和(i, right]
     */
    private void quickSort(int[] nums, int left, int right) {
        if(left >= right - 1){
            return;
        }
        int startIndex = left;
        int endIndex = right - 1;
        int ref = nums[endIndex];
        int border = left;
        while(startIndex < endIndex){
            int value = nums[startIndex];
            if(value < ref){
                ArrayUtil.swap(nums, startIndex, border);
                border ++;
            }
            startIndex ++;
        }

        //将参考值放入边界右侧,由于右侧都是大于等于参考值的,尽量避免最右边的值是数组中最小的
        ArrayUtil.swap(nums, endIndex, border);

        quickSort(nums, left, border);
        //注意,不要处理边界,会出现死循环
        quickSort(nums, border + 1, right);


    }
}

-7桶排序

public class BucketSorter implements Sorter {
    private Function<Integer, Integer> getBucketNumFunction;


    public BucketSorter(Function<Integer, Integer> getBucketNumFunction){
        this.getBucketNumFunction = getBucketNumFunction;
    }

    public BucketSorter(){
        this(n -> n);
    }

    private SimplyLinked[] createBuckets(int len){
        return new SimplyLinked[len];
    }

    private void insertValueToBuckets(SimplyLinked[] buckets, int val, int min, int max){

        int range = max - min + 1;

        int partitionSize = (range / buckets.length) + 1;
        int relate = val - min;
        int bucketIndex = relate / partitionSize;
        SimplyLinked theNode = new SimplyLinked(val);
        if(buckets[bucketIndex] == null){
            buckets[bucketIndex] = theNode;
        }else{
            SimplyLinked node = buckets[bucketIndex];
            if(val <= node.val){
                buckets[bucketIndex] = theNode;
                theNode.next = node;
                return;
            }

            SimplyLinked pref = node;
            SimplyLinked suff = node.next;
            while(true){
                if(suff == null){
                    pref.next = theNode;
                    return;
                }

                if(val <= suff.val){
                    pref.next = theNode;
                    theNode.next = suff;
                    return;
                }

                pref = suff;
                suff = pref.next;

            }

        }


    }

    public void buildSortArrayFromBuckets(SimplyLinked[] buckets, int[] nums){
        int index = 0;
        int len = buckets.length;
        for(int i = 0; i < len; i ++){
            SimplyLinked simplyLinked = buckets[i];
            while(simplyLinked != null){
                nums[index] = simplyLinked.val;
                index ++;
                simplyLinked = simplyLinked.next;
            }
        }

    }




    @Override
    public void sort(int[] nums) {
        int bucketNum = getBucketNumFunction.apply(nums.length);
        SimplyLinked[] buckets = createBuckets(bucketNum);
        int min = ArrayUtil.min(nums);
        int max = ArrayUtil.max(nums);
        for(int num : nums){
            insertValueToBuckets(buckets, num, min, max);
        }
        buildSortArrayFromBuckets(buckets, nums);

    }



    public static class SimplyLinked{
        int val;
        SimplyLinked next;
        public SimplyLinked(int val){
            this.val = val;
        }
    }
}

8计数排序

public class CountingSorter implements Sorter {

    /**
     * 根据待排序数组构建计数表
     */
    private int[] createCountArray(int[] nums, int min, int max){
        int len = max - min + 1;
        int offset = -min;
        int[] re = new int[len];
        for(int num : nums){
            re[num + offset] ++;
        }

        return re;
    }

    /**
     * 根据计数表构建排序好的数组
     */
    private void buildSortArray(int[] num, int[] countArray, int min){
        int len = countArray.length;
        int offset = -min;
        int index = 0;
        for(int i = 0; i < len; i ++){
            while(countArray[i] > 0){
                num[index] = i - offset;
                countArray[i] --;
                index ++;
            }
        }
    }

    @Override
    public void sort(int[] nums) {
        int min = ArrayUtil.min(nums);
        int max = ArrayUtil.max(nums);
        int[] countArray = createCountArray(nums, min, max);
        buildSortArray(nums, countArray, min);

    }
}

9基数排序(抄袭)

public class RadixSorterWithCounting implements Sorter {

    @Override
    public void sort(int[] nums) {
        int max=nums[0];
        for(int i=1;i<nums.length;i++) {
            if(nums[i]>max) {
                max=nums[i];
            }
        }
        int maxLength=(max+"").length();//得到数组最大值的位数,
        int[][] bucket=new int[10][nums.length];//此处10表示10个桶分别为0~9
        int[] bucketElemCount=new int [10];//为了记录每个桶中,实际存放了多少个数据,我们定义一个一维数组来记录各个桶的每次放入的数据个数,比如:bucketElemCount[0],记录的就是bucket[0] 桶的放入数据个数
        for(int i=0,n=1;i<maxLength;i++,n*=10){// n=1 表示处理个位,n=10表示处理十位,n=100表示处理百位 ......
            for(int j=0;j<nums.length;j++) {
                int digit=nums[j]/n%10;//取出每个元素的对应位的值
                bucket[digit][bucketElemCount[digit]]=nums[j];//放入到对应的桶中
                bucketElemCount[digit]++;
            }
            int index=0;
            for(int k=0;k<bucketElemCount.length;k++) {//遍历每一桶,并将桶中的数据,放入到原数组
                for(int l=0;l<bucketElemCount[k];l++) {
                    nums[index++]=bucket[k][l];
                }
                bucketElemCount[k]=0;//第i+1轮处理后,需要将每个 bucketElementCounts[k] = 0 即桶中数据置空方便下次使用
            }
        }

    }
    




}

10摆烂排序

public class UndoSorter implements Sorter {
    @Override
    public void sort(int[] nums) {
        //什么都不做
        ;
    }
}

10希尔排序

public class ShellSorter implements Sorter {
    @Override
    public void sort(int[] nums) {
        int len =nums.length;
        int step = len / 2;
        while(step > 0){
            insertSortWithStep(nums, step);
            step /= 2;
        }
    }

    public void insertSortWithStep(int[] nums, int step) {
        int len = nums.length;
        for(int i = 0; i < step; i ++){
            for(int j = i + step; j < len; j += step){
                int value = nums[j];
                int index = j - step;
                while(index >= 0 && value < nums[index]){
                    nums[index + step] = nums[index];
                    index -= step;
                }
                nums[index + step] = value;
            }
        }


    }
}

然后我们看一下我们的测试代码(也可以不看)

 public void analyze(String name, Sorter sorter, int ci, int min, int max, int... scale) {
        System.out.println("开始分析 -- "+ name);
        System.out.println("测试数据 -重复测试次数:"+ ci + " -数据范围:[" + min + "," + max + "] -测试规模:" + show(scale));
        for(int s : scale){
            System.out.println("数据规模为"+ s + ": 随机实验" + ci + "次");
            long[] times = new long[ci];
            for(int i =0; i < ci; i++){
                int[] nums = createRandomNums(s, min, max);
                long start = System.currentTimeMillis();
                sorter.sort(nums);
                long end = System.currentTimeMillis();
                boolean ok = SorterTest.isSort(nums);
                if(! ok){
                    throw new RuntimeException("排序出错");
                }
                long time = end - start;
                times[i] = time;
            }
            System.out.println("排序结果正确: 最小时间:" + min(times) + "ms, 最大时间: " + max(times) + "ms, 平均时间: " + avg(times) + "ms");
            System.out.println("\n");

        }


    }

    public int[] createRandomNums(int size, int min, int max) {
        int[] re = new int[size];
        for(int i = 0; i < size; i++){
            int ran =  min + (int)(Math.random() * (max-min+1));
            re[i] = ran;
        }

        return re;

    }

    public String show(int[] array){
        String re = "";
        for(int a : array){
            re += a;
            re += ", ";
        }
        return re;
    }

    public long max(long[] ls){
        long re = ls[0];
        for(int i = 1; i < ls.length; i ++){
            if(ls[i] > re){
                re = ls[i];
            }
        }
        return re;
    }

    public long min(long[] ls){
        long re = ls[0];
        for(int i = 1; i < ls.length; i ++){
            if(ls[i] < re){
                re = ls[i];
            }
        }
        return re;
    }

    public double avg(long[] ls){
//        double re = 0;
//        for (long l : ls) {
//            re += l / (double) ls.length;
//        }
//        return re;

        long re = 0;
        for (long l : ls) {
            re += l;
        }
        return re / (double)ls.length;
    }

实验方式:每种算法按照输入规模[100, 1000, 10000, 100000, 1000000(再大我电脑废了)]每种规模执行20次,获取这20次中的最小时间,最大时间,平均时间, 数据范围定在-5000到5000之间

实验截图如下

1选择排序 n2

2冒泡排序 n2

开始分析 -- 冒泡排序
测试数据 -重复测试次数:20 -数据范围:[-5000,5000] -测试规模:100, 1000, 10000, 100000, 1000000, 
数据规模为100: 随机实验20次
排序结果正确: 最小时间:0ms, 最大时间: 1ms, 平均时间: 0.1ms


数据规模为1000: 随机实验20次
排序结果正确: 最小时间:0ms, 最大时间: 1ms, 平均时间: 0.6ms


数据规模为10000: 随机实验20次
排序结果正确: 最小时间:30ms, 最大时间: 38ms, 平均时间: 31.85ms


数据规模为100000: 随机实验20次
排序结果正确: 最小时间:10371ms, 最大时间: 10906ms, 平均时间: 10537.65ms


数据规模为1000000: 随机实验20次
排序结果正确: 最小时间:1135613ms, 最大时间: 4379198ms, 平均时间: 1368180.65ms

-3插入排序 n2

开始分析 -- 插入排序
测试数据 -重复测试次数:20 -数据范围:[-5000,5000] -测试规模:100, 1000, 10000, 100000, 1000000, 
数据规模为100: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:0ms, 最大时间: 1ms, 平均时间: 0.05ms


数据规模为1000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:0ms, 最大时间: 1ms, 平均时间: 0.2ms


数据规模为10000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:7ms, 最大时间: 10ms, 平均时间: 7.6ms


数据规模为100000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:668ms, 最大时间: 777ms, 平均时间: 688.95ms


数据规模为1000000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:68983ms, 最大时间: 72561ms, 平均时间: 70087.0ms

-4归并排序 nlgn

开始分析 -- 归并排序
测试数据 -重复测试次数:20 -数据范围:[-5000,5000] -测试规模:100, 1000, 10000, 100000, 1000000, 
数据规模为100: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:0ms, 最大时间: 0ms, 平均时间: 0.0ms


数据规模为1000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:0ms, 最大时间: 1ms, 平均时间: 0.05ms


数据规模为10000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:0ms, 最大时间: 2ms, 平均时间: 1.0ms


数据规模为100000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:8ms, 最大时间: 11ms, 平均时间: 8.6ms


数据规模为1000000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:81ms, 最大时间: 89ms, 平均时间: 83.4ms

-5堆排序 nlgn

开始分析 -- 堆排序
测试数据 -重复测试次数:20 -数据范围:[-5000,5000] -测试规模:100, 1000, 10000, 100000, 1000000, 
数据规模为100: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:0ms, 最大时间: 1ms, 平均时间: 0.05ms


数据规模为1000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:0ms, 最大时间: 1ms, 平均时间: 0.15ms


数据规模为10000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:0ms, 最大时间: 2ms, 平均时间: 1.05ms


数据规模为100000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:8ms, 最大时间: 12ms, 平均时间: 9.55ms


数据规模为1000000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:98ms, 最大时间: 106ms, 平均时间: 99.9ms

-6快速排序 nlgn

开始分析 -- 快速排序
测试数据 -重复测试次数:20 -数据范围:[-5000,5000] -测试规模:100, 1000, 10000, 100000, 1000000, 
数据规模为100: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:0ms, 最大时间: 0ms, 平均时间: 0.0ms


数据规模为1000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:0ms, 最大时间: 0ms, 平均时间: 0.0ms


数据规模为10000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:0ms, 最大时间: 1ms, 平均时间: 0.65ms


数据规模为100000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:5ms, 最大时间: 10ms, 平均时间: 6.1ms


数据规模为1000000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:69ms, 最大时间: 77ms, 平均时间: 72.0ms

-7桶排序 n

开始分析 -- 桶排序
测试数据 -重复测试次数:20 -数据范围:[-5000,5000] -测试规模:100, 1000, 10000, 100000, 1000000, 
数据规模为100: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:0ms, 最大时间: 0ms, 平均时间: 0.0ms


数据规模为1000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:0ms, 最大时间: 1ms, 平均时间: 0.05ms


数据规模为10000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:0ms, 最大时间: 1ms, 平均时间: 0.45ms


数据规模为100000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:1ms, 最大时间: 3ms, 平均时间: 1.35ms


数据规模为1000000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:32ms, 最大时间: 96ms, 平均时间: 58.0ms

-8计数排序 n

开始分析 -- 计数排序
测试数据 -重复测试次数:20 -数据范围:[-5000,5000] -测试规模:100, 1000, 10000, 100000, 1000000, 
数据规模为100: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:0ms, 最大时间: 1ms, 平均时间: 0.1ms


数据规模为1000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:0ms, 最大时间: 1ms, 平均时间: 0.1ms


数据规模为10000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:0ms, 最大时间: 1ms, 平均时间: 0.3ms


数据规模为100000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:0ms, 最大时间: 1ms, 平均时间: 0.45ms


数据规模为1000000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:3ms, 最大时间: 4ms, 平均时间: 3.2ms

-9基数排序 n

开始分析 -- 基数排序
测试数据 -重复测试次数:20 -数据范围:[0,10000] -测试规模:100, 1000, 10000, 100000, 1000000, 
数据规模为100: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:0ms, 最大时间: 1ms, 平均时间: 0.05ms


数据规模为1000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:0ms, 最大时间: 1ms, 平均时间: 0.15ms


数据规模为10000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:0ms, 最大时间: 1ms, 平均时间: 0.15ms


数据规模为100000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:0ms, 最大时间: 1ms, 平均时间: 0.5ms


数据规模为1000000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:3ms, 最大时间: 4ms, 平均时间: 3.3ms

-10摆烂排序 1

开始分析 -- 摆烂排序
测试数据 -重复测试次数:20 -数据范围:[-5000,5000] -测试规模:100, 1000, 10000, 100000, 1000000, 
数据规模为100: 随机实验20次
|Exception in thread "main" java.lang.RuntimeException: 排序出错
    at com.oraen.oxygen.test.sort.SorterAnalyze.analyze(SorterAnalyze.java:39)
    at com.oraen.oxygen.test.sort.SorterAnalyze.main(SorterAnalyze.java:18)

-11希尔排序 1

开始分析 -- 希尔排序
测试数据 -重复测试次数:20 -数据范围:[0,10000] -测试规模:100, 1000, 10000, 100000, 1000000, 
数据规模为100: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:0ms, 最大时间: 0ms, 平均时间: 0.0ms


数据规模为1000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:0ms, 最大时间: 1ms, 平均时间: 0.05ms


数据规模为10000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:0ms, 最大时间: 1ms, 平均时间: 0.7ms


数据规模为100000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:8ms, 最大时间: 12ms, 平均时间: 9.1ms


数据规模为1000000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:98ms, 最大时间: 106ms, 平均时间: 101.0ms

性能统计表(时间单位为毫秒)

排序算法平均时间(一百)平均时间(一千)平均时间(一万)平均时间(十万)平均时间(百万)
选择排序0.10.95116.44297.25206812.95
冒泡排序0.10.631.8510537.651368180.65
插入排序0.050.27.6688.9570087.0
归并排序00.051.08.683.4
堆排序0.050.151.059.5599.9
快速排序000.656.172.0
桶排序00.050.451.3558.0
计数排序0.10.10.30.453.2
基数排序0.050.150.150.53.3
摆烂排序-
希尔排序00.050.79.1101.0

由于前面的3哥算法太慢了,100w数据人都快等废了,就不进行更大数据的测试了,不过不知道为什么插入排序居然这么猛,明明是相同的时间复杂度,nlogn中也是快排最快,时间复杂度为n的排序算法由于都需要假定某些输入条件,并且对空间有要求,虽然快,但是通用性不高。下面我们继续对后面的算法测试千万,亿,十亿数据的情况

归并排序 nlgn

     

开始分析 -- 归并排序
测试数据 -重复测试次数:20 -数据范围:[-5000,5000] -测试规模:10000000, 100000000, 1000000000, 
数据规模为10000000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:856ms, 最大时间: 919ms, 平均时间: 866.4ms


数据规模为100000000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:9052ms, 最大时间: 9534ms, 平均时间: 9258.15ms


数据规模为1000000000: 随机实验20次
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at com.oraen.oxygen.test.sort.SorterAnalyze.createRandomNums(SorterAnalyze.java:54)
    at com.oraen.oxygen.test.sort.SorterAnalyze.analyze(SorterAnalyze.java:32)
    at com.oraen.oxygen.test.sort.SorterAnalyze.main(SorterAnalyze.java:18)

堆排序 nlgn

开始分析 -- 堆排序
测试数据 -重复测试次数:20 -数据范围:[-5000,5000] -测试规模:10000000, 100000000, 1000000000, 
数据规模为10000000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:1630ms, 最大时间: 2151ms, 平均时间: 1745.2ms


数据规模为100000000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:24369ms, 最大时间: 31972ms, 平均时间: 26915.15ms


数据规模为1000000000: 随机实验20次
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at com.oraen.oxygen.test.sort.SorterAnalyze.createRandomNums(SorterAnalyze.java:54)
    at com.oraen.oxygen.test.sort.SorterAnalyze.analyze(SorterAnalyze.java:32)
    at com.oraen.oxygen.test.sort.SorterAnalyze.main(SorterAnalyze.java:18)

快速排序 nlgn

开始分析 -- 快速排序
测试数据 -重复测试次数:20 -数据范围:[-5000,5000] -测试规模:10000000, 100000000, 1000000000, 
数据规模为10000000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:2918ms, 最大时间: 3063ms, 平均时间: 2957.4ms


数据规模为100000000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:235940ms, 最大时间: 239646ms, 平均时间: 237175.15ms


数据规模为1000000000: 随机实验20次
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at com.oraen.oxygen.test.sort.SorterAnalyze.createRandomNums(SorterAnalyze.java:54)
    at com.oraen.oxygen.test.sort.SorterAnalyze.analyze(SorterAnalyze.java:32)
    at com.oraen.oxygen.test.sort.SorterAnalyze.main(SorterAnalyze.java:18)
 

桶排序 n

开始分析 -- 桶排序
测试数据 -重复测试次数:20 -数据范围:[-5000,5000] -测试规模:10000000, 100000000, 1000000000, 
数据规模为10000000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:394ms, 最大时间: 1421ms, 平均时间: 939.85ms


数据规模为100000000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:8498ms, 最大时间: 14307ms, 平均时间: 10664.95ms


数据规模为1000000000: 随机实验20次
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at com.oraen.oxygen.test.sort.SorterAnalyze.createRandomNums(SorterAnalyze.java:54)
    at com.oraen.oxygen.test.sort.SorterAnalyze.analyze(SorterAnalyze.java:32)
    at com.oraen.oxygen.test.sort.SorterAnalyze.main(SorterAnalyze.java:18)

计数排序 n

开始分析 -- 计数排序
测试数据 -重复测试次数:20 -数据范围:[-5000,5000] -测试规模:10000000, 100000000, 1000000000, 
数据规模为10000000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:14ms, 最大时间: 32ms, 平均时间: 17.4ms


数据规模为100000000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:146ms, 最大时间: 180ms, 平均时间: 151.25ms


数据规模为1000000000: 随机实验20次
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at com.oraen.oxygen.test.sort.SorterAnalyze.createRandomNums(SorterAnalyze.java:54)
    at com.oraen.oxygen.test.sort.SorterAnalyze.analyze(SorterAnalyze.java:32)
    at com.oraen.oxygen.test.sort.SorterAnalyze.main(SorterAnalyze.java:18)

基数排序 n

开始分析 -- 基数排序
测试数据 -重复测试次数:20 -数据范围:[0,10000] -测试规模:10000000, 100000000, 1000000000, 
数据规模为10000000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:14ms, 最大时间: 26ms, 平均时间: 16.65ms


数据规模为100000000: 随机实验20次
||||||||||||||||||||-排序结果正确: 最小时间:147ms, 最大时间: 162ms, 平均时间: 151.95ms


数据规模为1000000000: 随机实验20次
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at com.oraen.oxygen.test.sort.SorterAnalyze.createRandomNums(SorterAnalyze.java:54)
    at com.oraen.oxygen.test.sort.SorterAnalyze.analyze(SorterAnalyze.java:32)
    at com.oraen.oxygen.test.sort.SorterAnalyze.main(SorterAnalyze.java:18)

希尔排序

开始分析 -- 希尔排序

测试数据 -重复测试次数:20 -数据范围:[0,10000] -测试规模:10000000, 100000000, 1000000000,

数据规模为10000000: 随机实验20次

||||||||||||||||||||-排序结果正确: 最小时间:1718ms, 最大时间: 2532ms, 平均时间: 1942.05ms

数据规模为100000000: 随机实验20次

||||||||||||||||||||-排序结果正确: 最小时间:26549ms, 最大时间: 33565ms, 平均时间: 29073.1ms

数据规模为1000000000: 随机实验20次

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

at com.oraen.oxygen.test.sort.SorterAnalyze.createRandomNums(SorterAnalyze.java:54)

at com.oraen.oxygen.test.sort.SorterAnalyze.analyze(SorterAnalyze.java:32)

at com.oraen.oxygen.test.sort.SorterAnalyze.main(SorterAnalyze.java:18)

排序算法平均时间(千万)

平均时间

(亿)

平均时间

(十亿)

归并排序866.49258.15-
堆排序1745.226915.15-
快速排序2957.4237175.15-
桶排序939.8510664.95-
计数排序17.4151.25

-

基数排序16.65151.95
希尔排序1942.0529073.1

想解释的很多,但是感觉罄竹难书,就不说了,桶排序适合范围大的情况下,这个实验可能对他不公平,其实他还有很多优化空间,比如桶的数量在范围和数据数量中取最小值,太懒了,就不优化了,比较奇怪的是快排在1000w和1e数据时很慢,非常地奇怪。不知道是随机数不随机了还是咋地。而且插入排序和希尔排序比我想的快很多

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值