一.在算法设计中经常用到递归,我们先看看在什么时候通常适合递归。
1.有许多数学公式、数列等等的定义是递归,比如阶乘、斐波那契数列都是可以将其递归定义转化为对应的递归算法.比如求n!递归算法如下:
long jie_cheng(int n){ if(n == 0 || n == 1) return 1; else return n * jie_cheng(n - 1); }
2.我们碰到的很多数据结构它们本身就是通过递归定义的,比如我们大家都学过的单链表就是一种典型的递归数据结构,其节点定义如下:
typedef struct node{ ElemType data; //ElemType 自定以数据类型 struct node *next; //递归调用 };
3.问题的求解方法是递归的
比较典型的例子就是汉诺塔问题.这个在前面已经谈过就不多做阐述了,源码如下:
//递归模型如下
Hannota(n - 1, x, z, y);
Hannota(n, x, y, z) = Hannota(n, x, z); //将第n个圆盘从x塔移到z塔
Hannota(n - 1, y, x, z); //继续上述两个过程
void hannota(int n, char X, char Y, char Z){ if(n == 1) printf("\t将第%d个盘片从%c上移动到%c\n", n, X, Z); else{ Hannota(n - 1, X, Z, Y); //将x上n-1个盘子借z塔放到y塔上 printf("\t将第%d个盘子从%c上移到%c\n", n, X, Z); Hannota(n - 1, Y, X, Z); } }
二.递归模型
我们上述所讲的递归过程基本上都是有类似3中所写的递归模型的,递归模型是递归算法的抽象表示,它反映了一个递归问题的递归结构,比如1,其递归结构为:
f(n) == 1 n == 1
f(n) = n * f(n - 1) n > 1
三.递归设计步骤
1.正如我们之前讲到的,递归本身是一种分而治之的算法,它现将整个问题划分为若干个子问题,再分别求解子问题,最后得到整个问题的解,这是一个量变到质变的过程.
2.步骤一般为:通过计算求得递归模型(一定要包含递归出口),再根据这个递归模型编写算法.
//说了那么多,我们结合线性表举个实例,来练习一下.
问题:假设有一不带头结点的L,设计算法释放所有节点
//分析:如果我们先释放在递归,那么后序节点就断开了,因此必须先释放尾节点
1.递归模型
什么都不做 if(L == NULL)
myfree(L->next) if(L != NULL)
//假设节点为 LinkList(这是一个一级指针) void myfree(LinkList L){ if(L != NULL){ myfree(L->next); //这是一个从后往前释放的过程,先释放后面 free(L); } }
//如果有兴趣大家可以用递归求节点个数、正向、反向输出节点、删除值为x的节点dengdeng.
//--.--谢谢各位大佬捧场
//A step is for many steps.