//分治:划分、解子问题、组合 //每个递归算法均可以转换为迭代算法 #include <stdio.h> #include <stdlib.h> //寻找最大最小元素,最大比较次数 3*N/2 - 2 minmax(low,high) if(high - low = 1) if(arr[low] < arr[high]) return (arr[low],arr[high]) else return (arr[high],arr[low]) end if else mid = (low+high)/2 (x1,y1) = minmax(low,mid) (x2,y2) = minmax(mid+1,high) x = min(x1,x2) y = max(y1,y2) return (x,y) end if //寻找第k小元素或中项 O(NlogN) //每个递归调用划分步骤中,丢弃元素的固定部分,问题规模不断减小 select (A,low,high,k) p = high - low + 1 if(p < 44) Sort(A) return A[k] else q = p/5; 把A分成q组,每组5个元素;若不整除,排除剩余的元素 q中的每一组单独排序,找出中项,放入集合M mm = select(A,1,q,q/2) //找出中项集合的中项 把A分成三组:A1= {a|a<mm} A2 ={a|a=mm} A3 = {a|a > mm} case |A1| >= k : return select(A1,1,|A1|,k) |A1| + |A2| >= k: return mm |A1| + |A2| < k: return select(A3,1,|A3|,k-|A1|-|A2|) end case end if //大整数乘法 //把n位大整数X 分为n/2位的两部分 X1,X2,则X = X1*2^(n/2) + X2 幂运算可以做移位 //X*Y = X1*Y1*2^n + ((X1+X2)(Y1+Y2))-X1*Y1 - X2*Y2)*2^(n/2)+X2*Y2 只需要3次n/2规模的乘法和6次加减运算 //T(n) = 3T(n/2)+bn O(n^1.59) //矩阵乘法 //传统的O(n^3):乘法:n^3 加法:n^3-n^2 //优化 O(n^2.81):乘法7次、加法18次: T(N) = 7*T(N/2) + 18*(N/2)^2a /*增加减法以减少乘法:设置7个d,根据A,B的子矩阵计算,利用d组成C */ //最近点对问题 O(n*log n) 输入:平面上n个点的集合S 输出:S中两点的最小距离 以x坐标递增排序S Y = 以y坐标递增排序S Z = cp(1,n) cp(low,high) if(high - low +1 <=3) 直接计算距离 else mid = (high + low)/2 x0 = x(S[mid]) //找出x的中线 Zl = cp(low,mid) Zr = cp(mid+1,high) Z = min(Zl,Zr) k = 0 //从Y中抽取T,找出那些在中线附近Z区域的点 for(i = 1~n) if(|x(Y[i] - x0| <= Z) k = k+1 T[k] = Y[i] end if end for Z0 = 2Z for(i = 1~k-1) //对这些点上部的7个点比较距离 for(j = i+1 ~ min{i+7,k}) if(d[T[i],T[j]) < Z0 Z0 = d(T[i],T[j]) end for end for Z = min(Z,Z0) end if return Z