从入门开始手把手搭建千万级Java算法测试-归并排序和插入排序的比较

  第五天开始呢,我们讲解归并排序和插入排序进行比较的算法,从算法思路,到算法伪代码实现,到复杂度分析,从这里开始我们手把手搭建一个测试平台的基础,根据你自身硬件水平可以对下列代码进行从1000,到千万级测试,其中算法测试时间与你的机器硬件水平和实现的算法有关系,下面是算法的具体讲解。
(1)排序算法的思路
  归并(Merge)基本思想:是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。
  直接插入插排的基本思想是:当插入第i(i >= 1)时,前面的V[0],V[1],……,V[i-1]已经排好序。这时,用V[I]的排序码与V[i-1],V[i-2],…的排序码顺序进行比较,找到插入位置即将V[i]插入,原来位置上的元素向后顺移。

(2)算法伪代码

//直接插入排序:
Insertion_sort(A){
           for j←2  to length[A]{
                  temp = A[j];
                  i ←j-1;
		}
                  while (i>0 and A[i] > temp){
                          A[i+1]=A[i];
                           i--;
                   A[i+1] = temp;
	}
}
     //归并排序:
     void Merge( T A,T &B, s,m,e)//将A中的A[s..m]和A[m+1..e]合并成B[s..e]
   {
       for( j = m+1,k = s; j <=e && s<= m;k++)
      {
                if( A[j] < A[s] ) B[k] = A[j++];  
               esle B[k] = A[s++];
      }
      if( s <= m ) B[k..e] = A[s..m];
      if( j <= e)  B[k..e] = A[j..e];
    }


(3)复杂度分析
1.归并算法
T(n)c1代价为1,c2代价为2T(n/2),c3代价为n
故当n=1时,T(n)=Θ(1);
当n>1时,T(n)=2T(n/2)+Θ(n)
即归并排序的时间复杂度为O(nlgn)。
2.插入排序
Tmin(n)= Θ(1)全部有序
在这里插入图片描述
Tmax(n)= Θ(n^2)全部无序
在这里插入图片描述
即插入排序的时间复杂度为O(n^2)
3. 结论
   从时间复杂度平均分析的角度上来看,归并排序优于插入排序,而空间复杂度上两者都为O(1)是一样的

(4)代码主体部分

package runoob;
import java.util.Arrays;
/**
 * 归并排序
 */
public class MergeSort {
    // 将arr[l...mid]和arr[mid+1...r]两部分进行归并
    private static void merge(Comparable[] arr, int l, int mid, int r) {

        Comparable[] aux = Arrays.copyOfRange(arr, l, r + 1);// 初始化,i指向左半部分的起始索引位置l;j指向右半部分起始索引位置mid+1

        int i = l, j = mid + 1;
        for (int k = l; k <= r; k++) {

            if (i > mid) {  // 左半部分元素全部处理完毕
                arr[k] = aux[j - l];
                j++;
            } else if (j > r) {   // 右半部分元素全部处理完毕
                arr[k] = aux[i - l];
                i++;
            } else if (aux[i - l].compareTo(aux[j - l]) < 0) {  // 左半部分元素 < 右半部分元素
                arr[k] = aux[i - l];
                i++;
            } else {  // 左半部分元素 >= 右半部分元素
                arr[k] = aux[j - l];
                j++;
            }
        }
    }

    private static void sort(Comparable[] arr, int l, int r) {// 递归使用归并排序,对arr[l...r]的范围进行排序
        if (l >= r) {
            return;
        }
        int mid = (l + r) / 2;
        sort(arr, l, mid);
        sort(arr, mid + 1, r);
        // 对于arr[mid] <= arr[mid+1]的情况,不进行merge
        // 对于近乎有序的数组非常有效,但是对于一般情况,有一定的性能损失
        if (arr[mid].compareTo(arr[mid + 1]) > 0)
            merge(arr, l, mid, r);
    }

    public static void sort(Comparable[] arr) {

        int n = arr.length;
        sort(arr, 0, n - 1);
    }

    // 测试MergeSort
    public static void MergeSort_Incompear(long num){//归并插入比较
        Integer[] arr = SortHelper.generateRandomArray(num, 0, 100);
        Integer[] arr2=Arrays.copyOfRange(arr,0, Math.toIntExact(num));

        long start1=System.nanoTime();
        sort(arr);
        long end1=System.nanoTime();
        System.out.println("归并算法花费时间:" + (end1 - start1)/1000 + "(ms)");

        long start2=System.nanoTime();
        InsertionSort.sort(arr2);//调用往期插入排序内容
        long end2=System.nanoTime();
        System.out.println("插入算法花费时间:" + (end2 - start2)/1000 + "(ms)");
    }
}

  对应代码中的SortHelper类我们留一个小小的悬念,留到最后来进行叙说,其中目前来说他的方法generateRandomArray的参数为,(num,left,right)第一个参数参与算法生成的数量级,作为随机生成序列,它可以为千万,因为是long级别,left和right则为生成序列的大小范围,生成的序列为返回值类型为Integer[]。
(5)测试结果如下:

请添加图片描述

  因为算法的时间复杂度比较高,如果笔者有兴趣可以尝试千万级的算法测试,这里便不在赘述。

请添加图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值