3. else return (a[high],a[low])
4. end if
5. else
6. mid←|_(low+high)/2_|
7. (x1,y1)←minmax(a,low,mid)
8. (x2,y2)←minmax(a,mid+1,high)
9. x←min{x1,x2}
10. y←max{y1,y2}
11. return (x,y)
12.end if
代码第1行high-low=1表示数组长度为1,此时执行第2行~第4行代码直接比较数组的两个元素,选出最大值和最小值,此为函数的递归终止条件;代码第7行和第8行是两个递归调用,分别在数组的下标范围[low,mid]和
[mid+1,high]查找最小值和最大值,第9行比较两个最大值取其中较大者,第10行比较两个最小值取较大者。
代码的第2、9和10行涉及到元素的比较,第7、8行由于递归也产生元素比较,因此令算法总的元素比较次数为C(n),则有
⎩
⎨⎧>+==22)2/(221)(n n C n n C 若若 对递推式进行求解
2
2/3 2
2)2/( 2)2(2 2
2...22)2/(2 ...
2
48)8/(824)2)8/(2(4 2
4)4/(42)2)4/(2(22)2/(2)(1
1122111-=-+=+=+++++==+++=+++=++=++=+=∑-=-----n n C n C n C n C n C n C n C n C k k j j
k k k k k 得到minmax 算法的元素比较总次数为3n/2-2,优于直接比较的性能。
三、实验内容及要求
1. 编写程序使用分治算法MINMAX 求解数组的最小值和最大值,并用实际数组对算法进行测试。
2. 要求算法中元素比较的次数为3n/2-2,在程序中元素比较的地方进行记录,并在程序末尾输出数组最大值和最小值以及元素比较次数。
四、实验步骤
1. 定义结构体类型或类,用以在函数的返回值同时返回数组的最大值和最小值。 结构体定义可以参考:
struct T {
int max,min;
};
类的定义可以参考:
class T {
private :
int max,min;
public :
int getMax() {…}
int getMin() {…}
void setMax(int max) {…}
void setMin(int min) {…}
}
2. 编写函数MINMAX 求解数组最大值和最小值,函数头为:
T MINMAX(int a[],int low,int high)
a 为数组名,low 和high 分别为数组的下标上界和下界。
3.
在main 函数中使用给定数组{21,25,49,16,25,6,78,1}测试
MINMAX 函数并输出元素比较次数,效果如下图所示。
五、思考和作业
1. 试修改程序MINMAX ,使得当数组长度n 不是2的整数幂也能运行,并分析修改后算法的元素比较次数。
2. 使用分治算法解决最大子数组和问题,问题描述如下:
给定一个整数序列S ,找出S 中的连续子序列,使得该子序列和最大,要求算法时间复杂性为Θ(nlogn)。例如:-2, 11, -4, 13, -5, -2; 结果为20: (11, -4, 13)。
提示:
假定要寻找子数组S[low …high]的最大子数组,使用分治法将数组分解成两个尽可能想相等的子数组,找到子数组中点mid ,则S[low …high]中任何连续数组S[i …j]必然是一下三种情况之一:
● 完全位于S[low…mid]中,low≤i≤j≤mid
● 完全位于S[mid+1…high]中,mid
● 跨越中点mid ,low≤i≤mid因此,S[low …high]的一个最大子数组所处的位置必然是三种情况之一。可以通过递归方法求解A[low …mid]和A[mid+1…high]的最大子数组,则剩下的问题就是求解跨越中点的最大子数组,然后在三种情况下选择最大者。 Part 1
Part 2 the sub with largest sum may be in: Part 1
Part 2 or: Part 1 Part 2
recursion
The largest is
the result