算法(三)-分治和递归

算法(三)-分治和递归

  • 递归
  • 一、导引-归并排序
    • 问题导入和例子
    • 分治的基本策略
    • 算法分析
    • 算法实现
    • 排序算法比较
    • 讨论思考
    • 类似问题的算法
  • 二、二分搜索
  • 三、大整数乘法
    • 引入
    • 分治算法
    • 分治算法改进
    • 小结
  • 四、Strassen矩阵乘法
    • 传统的矩阵乘法
    • strassen矩阵乘法
    • 改进
  • 五、线性时间选择问题
    • 引入
    • 选择问题
    • 线性时间选择问题
    • 小结
  • 六、棋盘覆盖
    • 问题描述
    • 分治策略
    • 时间复杂度分析
    • 小结
  • 七、快速排序
  • 八、最接近点对问题
  • 九、循环赛日程表
  • 十、最大子段和
  • 课后题
    • 第n个斐波那契数列,可以用分治策求解吗?如果认为可以,请简要说明操作方法。

递归

直接或间接地调用自身的算法称为递归算法

阶乘函数:n!={1 n=0 ; n(n-1)! n>0}

int factorial(int n){
	if(n==0)
		return 1;
	return n*factorial(n-1)
} 

Fibonacci 数列:F(n)={1 n=0 ; 1 n=1 ; F(n-1)+F(n-2) n>1}

int fibonacci(int n){
	if(n<=1)
		return 1;
	return fibonacci(n-1) + fibonacci(n-2);
}

F ( n ) = 1 5 [ ( 1 + 5 2 ) n + 1 − ( 1 − 5 2 ) n + 1 ] F\left( n \right) =\frac{1}{\sqrt{5}}\left[ \left( \frac{1+\sqrt{5}}{2} \right) ^{n+1}-\left( \frac{1-\sqrt{5}}{2} \right) ^{n+1} \right] F(n)=5 1(21+5 )n+1(215 )n+1
Ackerman函数-双递归函数
排列问题
整数划分问题
Hanoi塔问题

void hanoi(int n,int a,int b,int c){
	if(n>0){
	/*其中,hanoi(n,a,b,c)表示将塔座a上自下而上,
	由大到小叠放在一起的n个圆盘依移动规则移至塔座b上并仍按同样顺序叠放。
	move(a,b)表示将塔座a上编号为n的圆盘移至b上*/
		hanoi(n-1,a,c,b);
		move(a,b);
		hanoi(n-1,c,b,a);
	}
}

通常,在一个算法中调用另一算法时,系统需在运行被调用算法之前先完成三件事:
1.将所有实参指针、返回地址等信息传递给被调用算法;
2.为被调用算法的局部变量分配存储区;
3.将控制转移到被调用算法的入口。

在从被调用算法返回调用算法时,系统相应地要完成三件事:
1.保存被调用算法的计算结果;
2.释放分配给被调用的数据区;
3.依照被调用算法保存的返回地址将控制转移到调用算法。

一、导引-归并排序

问题导入和例子

算法(三)-分治和递归_第1张图片
伪代码
算法(三)-分治和递归_第2张图片
算法(三)-分治和递归_第3张图片
算法(三)-分治和递归_第4张图片
算法(三)-分治和递归_第5张图片
算法(三)-分治和递归_第6张图片

分治的基本策略

分治法的基本思想是将一个规模为n的问题分解为k个规模较小的子问题,这些子问题互相独立且与原问题相同。递归地解这些子问题,然后将各子问题的解合并得到原问题的解。

分治法所能解决的问题一般具有以下几个特征:
1.该问题的规模缩小到一定的程度就可以容易地解决;
2.该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质
3.利用该问题分解出的子问题的解可以合并为该问题的解;
4.该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子问题。

算法分析

算法(三)-分治和递归_第7张图片

算法实现

算法(三)-分治和递归_第8张图片
左递归 右非递归
算法(三)-分治和递归_第9张图片
P1 理解算法,对前面的例子给出算法执行过程
P2 分析算法,给出T(n)公式,并推到计算得出O(T(n))

排序算法比较

算法(三)-分治和递归_第10张图片

讨论思考

算法(三)-分治和递归_第11张图片

类似问题的算法

算法(三)-分治和递归_第12张图片

二、二分搜索

顺序查找O(n)

template<class Type>
int BinarySearch(Type a[],const Type& x,int n){
	//找到x时返回其在数组中的位置,否则返回-1
	int left=0;
	int right=n-1;
	while(left<=right){
		int middle = (left+right)/2;
		if(x==a[middle])
			return middle;
		if(x>a[middle])
			left=middle+1;
		else
			right=middle-1; 	
	}
	return -1;
}
//时间复杂度O(logn)

三、大整数乘法

引入

大整数也称为高精度整数,准确来说,就是指普通程序设计语言中的整数类型值集范围以上的整数 - 比如16位大整数X=1552336656578988 。
计算机程序中,对于一些大整数可以用浮点数来表示它,但只能近似的表示该整数的大小。当大整数相加、相乘时,计算结果中的有效数字也受到了限制。

大整数的准确性在程序执行时如何保证?
算法(三)-分治和递归_第13张图片
算法(三)-分治和递归_第14张图片

分治算法

算法(三)-分治和递归_第15张图片
算法(三)-分治和递归_第16张图片
算法(三)-分治和递归_第17张图片

分治算法改进

算法(三)-分治和递归_第18张图片
算法(三)-分治和递归_第19张图片

小结

算法(三)-分治和递归_第20张图片

四、Strassen矩阵乘法

传统的矩阵乘法

算法(三)-分治和递归_第21张图片

strassen矩阵乘法

算法(三)-分治和递归_第22张图片
算法(三)-分治和递归_第23张图片
算法(三)-分治和递归_第24张图片
时间复杂度
算法(三)-分治和递归_第25张图片
最后结果
在这里插入图片描述

改进

算法(三)-分治和递归_第26张图片
算法(三)-分治和递归_第27张图片

五、线性时间选择问题

引入

算法(三)-分治和递归_第28张图片
算法(三)-分治和递归_第29张图片

选择问题

算法(三)-分治和递归_第30张图片
算法(三)-分治和递归_第31张图片
算法(三)-分治和递归_第32张图片
算法(三)-分治和递归_第33张图片
算法(三)-分治和递归_第34张图片
算法(三)-分治和递归_第35张图片

线性时间选择问题

算法(三)-分治和递归_第36张图片
算法(三)-分治和递归_第37张图片
算法(三)-分治和递归_第38张图片
算法(三)-分治和递归_第39张图片
算法(三)-分治和递归_第40张图片
算法(三)-分治和递归_第41张图片
算法(三)-分治和递归_第42张图片

小结

算法(三)-分治和递归_第43张图片

六、棋盘覆盖

问题描述

算法(三)-分治和递归_第44张图片
算法(三)-分治和递归_第45张图片
算法(三)-分治和递归_第46张图片
算法(三)-分治和递归_第47张图片

分治策略

算法(三)-分治和递归_第48张图片
算法(三)-分治和递归_第49张图片

时间复杂度分析

算法(三)-分治和递归_第50张图片

小结

算法(三)-分治和递归_第51张图片

七、快速排序

1.分解
2.递归求解
3.合并

T(n)=O(n2)
T(n)=O(nlogn)

八、最接近点对问题

推荐:最接近点对问题

九、循环赛日程表

推荐:循环赛日程表

十、最大子段和

最大子段和

课后题

第n个斐波那契数列,可以用分治策求解吗?如果认为可以,请简要说明操作方法。

可以,主要是将问题转换为矩阵乘幂的问题,用矩阵(Fn Fn-1)=(Fn-1 Fn-2)*A求A,再用递推式。计算A的n-1次方,与矩阵(F1 F0)相乘可得到Fn的值。

你可能感兴趣的:(数据结构与算法,算法,排序算法,数据结构)