递归概述
相当于是一个多线程协同运算的过程,相比较之前的排序,具有更好的时间复杂度,同时也有更多的限制。
实例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)