(算法)一个例子详解递归行为,master公式的使用;递归拓展归并排序

递归概述

相当于是一个多线程协同运算的过程,相比较之前的排序,具有更好的时间复杂度,同时也有更多的限制。

实例1

  • 以求某一范围内的最大值为例;找到arr[L...R]内的最大值
Public static int process(int[] arr,int L,int R){
  if(L == R){
    return = arr[L];
  }
  int mid = L+((R-L)>>1) ; //求该范围内的中间位置
  int Leftmax = process(arr,L,mid) ;
  int Rightmax = process(arr,mid+1,R) ;
  return math.max(Leftmax,Rightmax);
}

运行过程表达:

图 1

逻辑

首先找到该数组的中间位置,这里运用到位运算,((R-L)>>1就等于L到R位置的中点),在process函数内调用process,分为两部分,分别找到左半部分的Leftmax和右半部分的Rightmax,下面(math.max())则是求最大值的行为。

根据图1,我们可以清晰地看到整个运算过程,它相当于将数组的两部分同时进行找最大值的行为,无论是左边还是右边我都把它中分到底,再返回最大值,所以最后得到的值一定是这一部分最大的。

master公式

运用到master公式

基本表达式:T(N)= a*T(N/b) +O(N^d)

T(N) 为母体,也就是整个数据规模;以上面为例就是N

a 为调用了几次(相同运算部分的调用);以上面为例,a=2,调用了两次process,Left和Right

T(N/b) 为子部分,也就是我们每次调用运算的部分占的整体数据规模多少;以上面为例子,我们每次找1/2部分的最大值,得b=2

O(N^d) 为额外空间复杂度; 以上面为例,只有求中位数和最大值的行为,得O(1)

 master公式用于求时间复杂度

log(b,a) < d        O(N^d)

log(b,a) > d        O(N^log(b,a))

log(b,a) = d        O(N^d*logN)

例1表达式,T(N)= 2*T(N/2) +O(1)

得时间复杂度为O(N);

归并排序

整体就是一个递归行为,一个数组,先让它左边有序,右边有序,最后整体有序。

运行过程:

 逻辑

和前面的递归同理,将数组一分为二,分别去排序,再将有序的两部分继续排序。

准备一个空列表help,将两部分有序数组逐位从左至右进行比较,小的数字存放到空列表中,存好后再拷贝到arr数组中。 

代码实现(Java)

public static void DSort(int[] arr ,int L,int R){
  if(L == R){
    return;
  }
  int M = L+((R-L)>>1);
  process(arr,L,M);
  process(arr,M+1,R);
  merge(arr,L,M,R) 
}

public static void merge(int[] arr, int L,int M,int R){
  if(L == R){
    return;
  }
  int p1 = L;
  int p2 = M+1;
  int i =0;
  int[] help = new int[R-L+1];
  while(p1<=M && p2<=R){
    help[i++] = arr[p1] < arr[p2] ? arr[p1++]:arr[p2++];
  }
  while(p1<=M){
    help[i++] = arr[p1++];
  }
  while(p2<=R){
    help[i++] = arr[p2++];
  }
  for(int i = L;i <= R;i++){
    arr[i] = help[i];
  }
}

时间复杂度

运用master公式

T(N)= 2*T(N/2) +O(N)        (因为merge相当于把每个数字都遍历比较了一遍,所以额外空间复杂度为N)

得O(N*logN)

猜你喜欢

转载自blog.csdn.net/qq_48860282/article/details/123912714