递归
举例:
简单的来说递归就是一个函数直接或间接地调用自身,是为直接或间接递归。一般来说,递归需要有边界条件、递归前进段和递归返回段(其实就是进栈出栈的操作)。当边界条件不满足时,递归前进;当边界条件满足时,递归返回。用递归需要注意以下两点:(1) 递归就是在过程或函数里调用自身。(2) 在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口。
递归一般用于解决三类问题:
(1)数据的定义是按递归定义的。(Fibonacci函数,n的阶乘)
(2)问题解法按递归实现。(回溯)
(3)数据的结构形式是按递归定义的。(二叉树的遍历,图的搜索)
递归的缺点:
递归解题相对常用的算法如普通循环等,运行效率较低。因此,应该尽量避免使用递归,除非没有更好的算法或者某种特定情况,递归更为适合的时候。
在递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储,因此递归次数过多容易造成栈溢出。举例:
//直接递归求链表的长度 int GetLengthRecursive(linklist head) { if(head->next == NULL) return 0; return (GetLengthRecursive(head->next) + 1); }
- //用递归实现 从尾到头输出链表
- //很诚实的说盗用了别人的思想,真的太妙了,完全能看出你是否真的体会了递归的原理
- //正如那位哥们所说,递归就是一个进栈出栈的过程,链表前面的元素先进栈,在栈底,后面的元素后进栈,在栈顶,先出栈,哈哈。。。
- void recursion(node* head)
- {
- if(NULL==head)
- {
- return;
- }
- if(head->next!=NULL)
- {
- recursion(head->next); //前面的都是进栈过程,后面都是出栈过程
- }
- //如果把这句放在第二个if前面,那就是从头到尾输出链表,曾经的你或许是用while或者用for循环输出链表,现在你又多了一种方式
- cout<<head->data<<"\t";
- }