学习ios时,想要打印UIView的所有子控件,考虑使用递归来做这件事。
假设方法printSubView:(UIView*)
能实现这个功能;我们输入一个名为baseView的UIView,如果baseView没有有子控件,就没有要打印的东西;如果它有子控件就打印它的所有子控件,然后它的每个子控件再执行printSubView方法,直到没有子控件为止。
假设baseView有两个子控件a1、a2;
a1有子控件b1,a2没有子控件;
b1没有子控件;
当我们把这个baseView带入该方法时,首先会打印a1,然后调用
printSubView:a1,打印b1,接着会打印a2,由于a2没有子控件了,所有该方法终止。
- (void)printSubView:(UIView*)baseView
{
if (baseView.subviews) {
for (UIView* view in baseView.subviews) {
NSLog(@"%@",view);
[self printSubView:view];
}
}
}
这就是一个递归的应用。所谓的递归就是一个函数用自身来定义。
下面用一个数学表达式来说明编写递归时要注意四条基本法则。
f(x)=2f(x-1)+x,f(0)=1
1.基准,或者说是初始条件,即不用递归就知道的值,在上面的例子中就是f(0)=1;
2.不断推进,即递归向着基准进行,也就是不管x=n,这个n的值为多少,最终能把f(n)变成用f(0)表达的式子。
3.假设每一步递归都能顺利运行;在设计递归程序时,追踪实际的递归调用序列是很困难的,把这一困难的任务交给计算机去做,假定它能做的很好。
4.合成效益法则;简单说就是不要再递归中做重复的工作,比如我们想要得到g(100)的值,但是在递归的过程中需要多次计算g(99),这就违反了合成效益法则。这点在斐波那契数列中体现的很明显.
所谓的斐波那契数列,用数学表达式表现出来就是:
F(n) = F(n-1) + F(n-2)
F(1) = 1
F(2) = 1
如果我们用下面这个递归算法来求斐波那契数列
- (long)fibonacci:(long)num withArray:(int*)array
{
array[num]++;
if (num<=2) {
return 1;
}else{
return [self fibonacci:num - 1 withArray:array] + [self fibonacci:num - 2 withArray:array];
}
}
不难发现我们计算fibonacci(10)
的时候需要算fibonacci(9)+fibonacci(8)
,
算fibonacci(9)
的时候需要算fibonacci(8)+fibonacci(7)
……
用下面的代码来显示每个fibonacci(i)的计算次数
int a[45];
for (int i= 0; i<45; i++) {
a[i]=0;
}
NSLog(@"fibonacci(10)=%ld",[self fibonacci:10 withArray:a]);
for (int i= 0; i<45; i++) {
if (a[i]!=0) {
NSLog(@"fib(%d)算了%d次",i,a[i]);
}
}
运行程序得
fib(1)算了21次
fib(2)算了34次
fib(3)算了21次
fib(4)算了13次
fib(5)算了8次
fib(6)算了5次
fib(7)算了3次
fib(8)算了2次
fib(9)算了1次
fib(10)算了1次
这里有多次的重复计算。num稍稍增大时,计算时间就会特别长。