分治法之选择问题 (1)
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
最坏情况时间
Select的最坏情况时间是O( n 2 ) Select的平均情况时间是O(n)
最坏情况下的特例: 输入a恰好使对Partition的第i次调用选用的划分
元素是第i小元素,而k=n。 此时,(区间下界)m随
着Partition的每一次调用而仅增加1,j保持不变。
Partition最终需要调用n次。 则n次调用的时间总量是:
k<j: 设S是a[1:j-1]中元素的集合
return(Select2(S,k,j-1)) else:设R是a[j+1:n]中元素的集合 return(Select2(R,k-j,n-j))
}
Select2的待解决问题
算法中需要解决的两个问题 1) 如何确定子集合的中间值 当r较小时,采用InsertionSort(a,i,j)直接对每组 的r个元素分类,在分类好的序列中,中间元素即为当 前r个元素中的中间位置下标对应的元素。
7个乘法和10个加 (减)法
则:
C11 P S T V C12 P T C21 Q S C22 P R Q U
8个加(减)法
斯特拉森时间复杂度
b T (n) 2 7 T ( n / 2) an n2 n2
斯特拉森矩阵乘法目前只具有理论意义。 n2相当大时才会优于通常的矩阵乘法。 T (只有当 n) an (1 7 / 4 (7 / 4) 2 (7 / 4) k 1 ) 7 k T (1) (n≧120 2 ) log n log n
选择问题
1. 问题描述 在n个元素的表a[1:n]中确定第k小元素,1≤k≤n。 2. 设计思路 利用Partition过程。在第一次划分后划分元素v测定在a[j] 的位置上,则有j-1个元素小于或等于a[j],且有n-j个元素大 于或等于a[j]。此时, 若k=j,则a[j]即是第k小元素;否则, 若k<j,则a[1:n]中的第k小元素将出现在a[1:j-1]中, 且仍是a[1:j-1]中的第k小元素; 若k>j,则a[1:n]中的第k小元素将出现在a[j+1:n], 是a[j+1:n]中的第k-j小元素。
斯特拉森矩阵乘法
设矩阵A和B是两个n×n矩阵,讨论矩阵加法的时间复 杂度和矩阵乘法的时间复杂度。 观察:矩阵乘法的花费比矩阵加法大 。 矩阵加法:Θ( n2 )
3 矩阵乘法:Θ( n)
C (i, j )
1k n
A(i, k )B(k , j)
1 i, j n
分治法解决矩阵乘法(降低计算复杂度)
cn (7 / 4)
7
cnlog 4 log 7 log 4 nlog 7 (c 1)nlog 7 (nlog 7 ) (n 2.81 )
Leabharlann Baidu
斯特拉森矩阵乘法
假设:n=2k
A11 A 21
其中:
A12 B11 B A22 21
B12 C11 C12 B22 C21 C22
技巧:增加加法减少乘法
C11 A11B11 A12 B21 C12 A11 B12 A12 B22 C21 A21 B11 A22 B21 C22 A21 B12 A22 B22
利用Partition实现的选择算法实例分析
算法复杂度分析
假设 ① a中的元素互异; ② 随机选取划分元素,且选择a[m:p-1]中任一元素作为划分 元素的概率相同。 分析 在Select中每次调用Partition(m,j),所需的元素比较次是 j-m+1。 在执行一次Partition后,或者找到第k小元素,或者将在缩 小的子集(a[m,k-1]或a[k+1,j])中继续查找。缩小的子集的元 素数将至少比上一次划分的元素数少1。
利用Partition实现的选择算法
public static void Select(int n,int k) {//在数组a[1],…,a[n]中找第k小元素s并把它放在位置k,假设1≤k≤n。 //将剩下的元素按如下方式排列,使a[k]=t,对于1≤m<k,有a[m]≤t;对 于k<m≤n,有a[m]≥t。a[n+1]=+∞ int m,r,j; m=1;r=n+1;a[n+1]=10000; while(true) //每当进入这一循环时,1≤m≤k≤r≤n+1 { j=r; //将剩余元素的最大下标加1后给j j=Partition(m,j); //返回j,它使得a[j]是第j小的值 if(k<j) r=j; //j是新的上界 else if(k==j) return; else m=j+1; //j+1是新的下界 } }
( (i 1)) (n 2 )
1
n
最坏情况时间是O(n)的选择算法
基本思想:精心挑选划分元素v 方法:二次取中间值 目的:使v比一部分元素小比另一部分元素大
使用二次取中规则的选择算法的说明性描述
public static int Select2(int a[],int k,int n) { //在集合a中找第k小元素 ① 若n≤r,则采用插入法直接对a分类并返回第k小元素。 ② 把a分成大小为r的个子集合,忽略剩余的元素。 ③ 设 M m1 , m2 ,, mn / r 是上面 n / r 个子集合的中间值的集合。 ④ v Select 2( M , / 2 n / r ) n / r , ⑤ 用Partition划分a,v作为划分元素。 ⑥ 假设v在位置j。 ⑦ case k=j: return(v);
斯特拉森矩阵乘法的思想
令:
P ( A11 A22 )( B11 B22 ) Q ( A21 A22 ) B11 R A11 ( B12 B22 ) S A22 ( B21 B11 ) T ( A11 A12 ) B22 U ( A21 A11 )( B11 B12 ) V ( A12 A22 )( B21 B22 )
2) 如何保存n / r 个子集合的中间值 注:各组找到的中间元素值将调整到数组a的前 部,连续保存,从而可用递归调用的方式对这些中间 值进行排序并找出中间值的中间值。
Select2的实现
public static int Sel(int m,int p,int k) {//返回一个i,使得i属于[m,p],且a[i]是a[m:p]中第k小元素,r是一个全程变量,其取值为一 个大于1的整数。 int i,j,n,temp; if(p-m+1<=r) { InsertionSort(m,p); return(m+k-1);//返回第k小元素的位置 } while(true) { n=p-m+1; //元素数 for(i=1;i<=n/r;i++) //计算中间值 { InsertionSort(m+(i-1)*r,m+i*r-1); //将中间值收集到a[m:p]的前部 temp=a[m+i-1]; a[m+i-1]=a[m+(i-1)*r+r/2-1]; a[m+(i-1)*r+r/2-1]=temp; } j=Sel(m,m+n/r-1, ((n/r)+1)/2); //二次取中求mm temp=a[m]; a[m]=a[j]; a[j]=temp; //交换a[m]与a[j] j=Partition(m,p); if((j-m+1)==k) return(j); else if(j-m+1>k) p=j-1; else { k=k-(j-m+1); m=j+1; } } }