# -*- coding:utf-8 # -*- ''' how to understand recursion: 1 首先是思想方法上要转变,不要试图解决问题(这是常规的思考方式),而应该“鼠目寸光”地只想解决一点点, 要点是,解决一点点之后,剩下来的问题还是原来的问题,但规模要比原问题小了。 2 思想和语言是密切相关的,所以问题的提法也很重要。一个问题这样提可能感觉很难写出递归,换种提法,可能就写出来了。 平时就要注意用递归的方式思考,譬如什么是链表?以递归来看就是一个指针,指向一个含有链表的指针。 一旦你用这种方式看待链表,你会发现写链表的代码非常容易。反之,则非常容易拖泥带水。 3 从代码层面看,递归就是函数的循环,所以只要透彻理解函数,写递归代码没什么难的 写出递归函数也就是要处理好递归的3个主要的点: a)出口条件,即递归“什么时候结束”,这个通常在递归函数的开始就写好; b) 如何由"情况n" 变化到"情况n+1",也就是非出口情况,也就是一般情况——"正在"递归中的情况; c) 初始条件,也就是这个递归调用以什么样的初始条件开始 可以说,上述a,b,c三个条件组成了我们的递归函数。解决好上述3点,也就很容易地写出一个递归函数。剩下的就是去学习学习“数学归纳法”, 对递归最恰当的比喻,就是查词典。我们查词典的过程,本身就是递归。 想象用一本纯英文词典查单词,要查某一个单词的意思,翻到这个单词时,看解释,发现解释中有一个单词不认识, 所以,无法明白这个要查的单词是什么意思;这时,再用这本词典(函数本身)查那个不认识的单词,又发现查的第2个单词的解释中又有一个单词不认识, 那么,又再用这本词典查第3个不认识的单词,这样,一个一个查下去,直到解释中所有单词都认识, 这样就到底了,就明白了最后一个单词是什么意思,然后一层一层倒回来,就知道我最初想查的第1个单词是什么意思了,问题就解决了。 recursion and stack 这个要好好学习一下: 调用栈描述的是函数之间的调用关系,它由多个栈zhen组成,每栈zhen对应着一个未运行完成的函数 栈zhen中保存该函数的返回地址和局部变量,因而不仅能在函数执行完毕之后找到正确的返回地址, 而且还自然的保证了不同函数之间的局部变量不相干(因为不同函数对应着不同的栈zhen) Note: C语言调用栈来描述函数之间的关系,调用栈由栈zhen组成,每个栈zhen对应着一个未运行完的函数 在gdb中可以用backtrace命令打印所有栈zhen的信息 调用栈并不储存在可执行文件中,而是在运行时创建。调用栈所在的段称为 堆栈段,它有自己的大小, 如果调用次数多了,就会产生若干个栈帧,便会发生越界,这种情况称为栈溢出。 由于局部变量也是放在堆栈段的,所以局部变量太大也会造成栈溢出,这就是为什么要把较大的数组放在main函数外的原因。 '''