最近看算法导论,前面说了几种排序算法,于是我就都实践了一把,并且写了个简单的程序测试他们的正确性和性能,看能否和理论对的上,虽然我考虑到系统调度等因素实验其实并不是很严谨,主要是作为娱乐吧哈哈哈哈。本次排序算法包括
-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.1 | 0.95 | 116.4 | 4297.25 | 206812.95 |
冒泡排序 | 0.1 | 0.6 | 31.85 | 10537.65 | 1368180.65 |
插入排序 | 0.05 | 0.2 | 7.6 | 688.95 | 70087.0 |
归并排序 | 0 | 0.05 | 1.0 | 8.6 | 83.4 |
堆排序 | 0.05 | 0.15 | 1.05 | 9.55 | 99.9 |
快速排序 | 0 | 0 | 0.65 | 6.1 | 72.0 |
桶排序 | 0 | 0.05 | 0.45 | 1.35 | 58.0 |
计数排序 | 0.1 | 0.1 | 0.3 | 0.45 | 3.2 |
基数排序 | 0.05 | 0.15 | 0.15 | 0.5 | 3.3 |
摆烂排序 | - | ||||
希尔排序 | 0 | 0.05 | 0.7 | 9.1 | 101.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.4 | 9258.15 | - |
堆排序 | 1745.2 | 26915.15 | - |
快速排序 | 2957.4 | 237175.15 | - |
桶排序 | 939.85 | 10664.95 | - |
计数排序 | 17.4 | 151.25 | - |
基数排序 | 16.65 | 151.95 | |
希尔排序 | 1942.05 | 29073.1 |
想解释的很多,但是感觉罄竹难书,就不说了,桶排序适合范围大的情况下,这个实验可能对他不公平,其实他还有很多优化空间,比如桶的数量在范围和数据数量中取最小值,太懒了,就不优化了,比较奇怪的是快排在1000w和1e数据时很慢,非常地奇怪。不知道是随机数不随机了还是咋地。而且插入排序和希尔排序比我想的快很多