专题二:递归
递归定义:
在定义一个过程或函数的时候,又出现了调用本过程或者函数的成分,即调用它自己本身,这称为直接递归,若过程或函数f调用过程或函数g,而g又调用f,这称为间接递归。
递归模型:
递归模型反映一个递归问题的递归结构,例如:
(1)、f(1)
(2)、f(n)=n*f(n-1) n>1
其中,(1)给出了递归的终止条件,一般我们称为递归出口,(2)给出了f(n)的值与f(n-1)的值之间的关系,称为递归体。
一般地,一个递归模型是由递归出口和递归体构成,前者确定递归到何时为止,后者确定递归的方法。
递归的执行过程:
递归是把一个不能或不好直接求解的“大问题”转化成一个或几个“小问题”来解决。再把这些“小问题”进一步分解成更小的问题来解决。如此分解,直到每个小问题都可以直接解决(此时分解到递归出口)。在这过程中,应该注意:“大问题”和“小问题”必须类似。分解过程中一但遇到递归出口,分解过程结束,开始求值过程。因此,递归的执行过程由分解和求值两部分构成。
求解递归问题有两中方法,一种是直接求值,不需要回溯,另一种是不能直接求值,需要回溯,这两种方式在转换成非递归问题时采用的方法也不同,直接求值使用一些间接变量保存中间结果,称为直接转换法。间接求值需要回溯,所以有用栈保存中间结果,称为间接转换法。
下面举例来进一步说明问。
void reverse( )
{
char ch;
scanf( "%c",&ch );
if( ch!='.' )
{
reverse( );
printf( "%d",ch );
}
}
上面这个函数的功能是读入一串任意长度的字符串,该字符串以'.'结束,并打印出该字符串的倒序。
-----------------
下面是一个函数的定义:
|x-10 x>100 递归出口
f(x) = |
|f(f(x+11) x<=100 递归体
递归求值:
int m( int x )
{
int temp;
if( x>100 )
return ( x-10 );
else
{
temp=m( x+11 );
return m( temp );
}
}
非递归球值:
int fun( int x )
{
int num=1,temp;
if( x>100 )
return ( x-10 );
else
{
num ++ ;
temp = x+11;
}
while( num>0 )
{
if( temp > 100 )
{
num --;
temp = temp-10;
}
else
{
num ++;
temp = temp+11;
}
}
}
-----------------------------------------------------
下面举一个例子,分别用递归和非递归来前序遍历二叉树:
其中二叉树的结点定义为:
typedef struct node
{
char data;
struct node *left,*right;
} tree;
递归:
void pro( tree * t )
{
if( t!=NULL )
{
printf( "%c",t->data );
pro( t->left );
pro( t->right );
}
}
非递归:
void pro( tree * t)
{
tree stack[100],node;
int top;
stack[top] = t; //将根结点入栈
while( top>0 )
{
node = stack[top] //出栈
top --;
printf( "%c",node->data );
if( node->right!=NULL ) //若右子树为空,则将其根结点入栈
{
top ++;
stack[top] = node->right;
}
else //若左子树不为空,则将其根结点入栈
{
top ++;
stack[top] = node->left;
}
}
}