符合中小企业对网站设计、功能常规化式的企业展示型网站建设
本套餐主要针对企业品牌型网站、中高端设计、前端互动体验...
商城网站建设因基本功能的需求不同费用上面也有很大的差别...
手机微信网站开发、微信官网、微信商城网站...
一、使用递归的背景
创新互联公司是网站建设技术企业,为成都企业提供专业的做网站、成都网站制作,网站设计,网站制作,网站改版等技术服务。拥有十载丰富建站经验和众多成功案例,为您定制适合企业的网站。十载品质,值得信赖!
先来看一个☝️接口结构:
这个孩子,他是一个列表,下面有6个元素
展开children下第一个元素[0]看看:
发现[0]除了包含一些字段信息,还包含了 children 这个字段(喜当爹),同时这个children下包含了2个元素:
展开他的第一个元素,不出所料,也含有children字段(人均有娃)
可以理解为children是个对象,他包含了一些属性,特别的是其中有一个属性与父级children是一模一样的,他包含父级children所有的属性。
比如每个children都包含了一个name字段,我们要拿到所有children里name字段的值,这时候就要用到递归啦~
二、find_children.py
拆分理解:
1.首先import requests库,用它请求并获取接口返回的数据
2.若children以上还有很多层级,可以缩小数据范围,定位到children的上一层级
3.来看看定义的函数
我们的函数调用:find_children(node_f, 'children')
其中,node_f:json字段
children:递归对象
以下这段是实现递归的核心:
if items['children']:
items['children']不为None,表示该元素下的children字段还有子类数据值,此时满足if条件,可理解为 if 1。
items['children']为None,表示该元素下children值为None,没有后续可递归值,此时不满足if条件,可理解为 if 0,不会再执行if下的语句(不会再递归)。
至此,每一层级中children的name以及下一层级children的name就都取出来了
希望到这里能帮助大家理解递归的思路,以后根据这个模板直接套用就行
(晚安啦~)
源码参考:
首先我们要了解一下什么是递归。
递归法,递归法就是利用上一个或者上几个状态来求取当前状态的值(个人看法)。也可以说成函数自己调用自己的一种解决问题的策略。因此递归法通常是依托函数来实现的,递归函数总是会有一个出口,我们在解决递归问题时,只需要找出递归的关系式以及递归函数的出口(这两个可以说是递归函数的核心了)。下面我将在这里举求斐波那契值的例子带领着大家具体的实践一下递归法。
很显然递归函数的递推式是:fib(n) = fib(n-1)+fib(n-2)。
递归函数的出口是当n为1时返回1,当n为0时返回0。
最后递归函数的核心代码就可以写出了:
然后总的代码就是:
具体思路如下:
语句 return fib(n-1)+fib(n-2)的意思就是向前求斐波那契值,直到n-1=1,n-2=0
因为只有第1个和第0个斐波那契值是确定的
例:
当n=3时
第一次调用函数fib会执行第三条语句(因为n1)这样求回返回fib(2)+fib(1)
第二次调用函数时,因为21所有会返回fib(1)+fib(0);因为1不大于1,所以调用函数时
会执行第二条语句返回1值。
第三次调用函数,会执行第一和第二条语句,依次返回0和1从而求得fib(2)
fib(3)=fib(2)+fib(1)
fib(2)=fib(1)+fib(0)
即fib(3)=fib(1)+fib(0)+fib(1)=2*fib(1)+fib(0)
函数的递归调用
递归问题是一个说简单也简单,说难也有点难理解的问题.我想非常有必要对其做一个总结.
首先理解一下递归的定义,递归就是直接或间接的调用自身.而至于什么时候要用到递归,递归和非递归又有那些区别?又是一个不太容易掌握的问题,更难的是对于递归调用的理解.下面我们就从程序+图形的角度对递归做一个全面的阐述.
我们从常见到的递归问题开始:
1 阶层函数
#include iostream
using namespace std;
int factorial(int n)
{
if (n == 0)
{
return 1;
}
else
{
int result = factorial(n-1);
return n * result;
}
}
int main()
{
int x = factorial(3);
cout x endl;
return 0;
}
这是一个递归求阶层函数的实现。很多朋友只是知道该这么实现的,也清楚它是通过不断的递归调用求出的结果.但他们有些不清楚中间发生了些什么.下面我们用图对此做一个清楚的流程:
根据上面这个图,大家可以很清楚的看出来这个函数的执行流程。我们的阶层函数factorial被调用了4次.并且我们可以看出在调用后面的调用中,前面的调用并不退出。他们同时存在内存中。可见这是一件很浪费资源的事情。我们该次的参数是3.如果我们传递10000呢。那结果就可想而知了.肯定是溢出了.就用int型来接收结果别说10000,100就会产生溢出.即使不溢出我想那肯定也是见很浪费资源的事情.我们可以做一个粗略的估计:每次函数调用就单变量所需的内存为:两个int型变量.n和result.在32位机器上占8B.那么10000就需要10001次函数调用.共需10001*8/1024 = 78KB.这只是变量所需的内存空间.其它的函数调用时函数入口地址等仍也需要占用内存空间。可见递归调用产生了一个不小的开销.
2 斐波那契数列
int Fib(int n)
{
if (n = 1)
{
return n;
}
else
{
return Fib(n-1) + Fib(n-2);
}
}
这个函数递归与上面的那个有些不同.每次调用函数都会引起另外两次的调用.最后将结果逐级返回.
我们可以看出这个递归函数同样在调用后买的函数时,前面的不退出而是在等待后面的结果,最后求出总结果。这就是递归.
3
#include iostream
using namespace std;
void recursiveFunction1(int num)
{
if (num 5)
{
cout num endl;
recursiveFunction1(num+1);
}
}
void recursiveFunction2(int num)
{
if (num 5)
{
recursiveFunction2(num+1);
cout num endl;
}
}
int main()
{
recursiveFunction1(0);
recursiveFunction2(0);
return 0;
}
运行结果:
1
2
3
4
4
3
2
1
该程序中有两个递归函数。传递同样的参数,但他们的输出结果刚好相反。理解这两个函数的调用过程可以很好的帮助我们理解递归:
我想能够把上面三个函数的递归调用过程理解了,你已经把递归调用理解的差不多了.并且从上面的递归调用中我们可以总结出递归的一个规律:他是逐级的调用,而在函数结束的时候是从最后面往前反序的结束.这种方式是很占用资源,也很费时的。但是有的时候使用递归写出来的程序很容易理解,很易读.
为什么使用递归:
1 有时候使用递归写出来的程序很容易理解,很易读.
2 有些问题只有递归能够解决.非递归的方法无法实现.如:汉诺塔.
递归的条件:
并不是说所有的问题都可以使用递归解决,他必须的满足一定的条件。即有一个出口点.也就是说当满足一定条件时,程序可以结束,从而完成递归调用,否则就陷入了无限的递归调用之中了.并且这个条件还要是可达到的.
递归有哪些优点:
易读,容易理解,代码一般比较短.
递归有哪些缺点:
占用内存资源多,费时,效率低下.
因此在我们写程序的时候不要轻易的使用递归,虽然他有他的优点,但是我们要在易读性和空间,效率上多做权衡.一般情况下我们还是使用非递归的方法解决问题.若一个算法非递归解法非常难于理解。我们使用递归也未尝不可.如:二叉树的遍历算法.非递归的算法很难与理解.而相比递归算法就容易理解很多.
对于递归调用的问题,我们在前一段时间写图形学程序时,其中有一个四连同填充算法就是使用递归的方法。结果当要填充的图形稍微大一些时,程序就自动关闭了.这不是一个人的问题,所有人写出来的都是这个问题.当时我们给与的解释就是堆栈溢出。就多次递归调用占用太多的内存资源致使堆栈溢出,程序没有内存资源执行下去,从而被操作系统强制关闭了.这是一个真真切切的例子。所以我们在使用递归的时候需要权衡再三.
简单说,解决以上问题的思路是,循环执行n*n-1,直到n=1时。
#!/usr/local/bin/python3.3def recursion(n): #定义函数 if n == 1: return 1 else:
return n * recursion(n-1)print(recursion(10))
该示例执行结果是:
如何理解呢?第一点,函数中,调用自身函数的那部分句子,即return n *
recursion(n-1),把recursion(n-1)想像成另一个独立的函数,该函数的功能返回n-1的值,如果n的值是1,则返回1,函数运行结束。第二点,直观的看,可以把return
n * recursion(n-1)看成return n*(n-1)*(n-2)...1。而递归函数无非是在指定的条件下做普通的循环而已。
递归的思想主要是能够重复某些动作,比如简单的阶乘,次方,回溯中的八皇后,数独,还有汉诺塔,分形。
由于堆栈的机制,一般的递归可以保留某些变量在历史状态中,比如你提到的return x * power..., 但是某些或许庞大的问题或者是深度过大的问题就需要尽量避免递归,因为可能会栈溢出。还有一个问题是~python不支持尾递归优化!!!!所以~还是尽量避免递归的出现。
def power(x, n)
if n 0:
return 1
return x * power(x, n - 1)
power(3, 3)
3 * power(3, 2)
3 * (3 * power(3, 1))
3 * (3 * (3 * power(3, 0)))
3 * (3 * (3 * 1)) 这里n = 0, return 1
3 * (3 * 3)
3 * 9
27
当函数形参n=0的时候,开始回退~直到第一次调用power结束。
可以看出来的是,该题可以用斐波那契数列解决。
楼梯一共有n层,每次只能走1层或者2层,而要走到最终的n层。不是从n-1或者就是n-2来的。
F(1) = 1
F(2) = 2
F(n) = F(n-1) + F(n-2) (n=3)
这是递归写法,但是会导致栈溢出。在计算机中,函数的调用是通过栈进行实现的,如果递归调用的次数过多,就会导致栈溢出。
针对这种情况就要使用方法二,改成非递归函数。
将递归进行改写,实现循环就不会导致栈溢出