004-数据结构与算法-栈和递归的关系

栈的应用-递归

上一节我们讲到了栈这种数据结构,那么在实际编程中有哪些应用呢?这篇文章我们来研究一下栈的一种应用-递归

递归的基本思想

递归的基本思想,是把规模较大的一个问题,分解成规模较小的多个子问题去解决,而每一个子问题又可以继续拆分成多个更小的子问题。
最重要的一点就是假设子问题已经解决了,现在要基于已经解决的子问题来解决当前问题;或者说,必须先解决子问题,再基于子问题来解决当前问题。

总的来说,使用递归来解决问题就是将复杂的问题简单化。但是有些时候并不能使用递归解决问题,那么在什么情况下我们才能去使用递归呢?有以下三种情况:

  1. 定义是递归的
    比如很多数学定义本身就是递归定义;例如大家非常熟悉的阶乘:
Fact(n)
(1) n=0, 1;
(2) n > 1, n*Fact(n-1);

long Fact(Long n){
if(n=0) return -1;
else return n * Fact(n-1);
}

Fib(n)
(1) n=1 n=2, 1;
(2) n > 2, Fib(n-1) + Fib(n-2);

long Fib(Long n){
 if(n == 1 || n == 2) return 1;
 else return Fib(n-1)+Fib(n-2);
}

对于类似于这种复杂的问题,能够分解成几个简单且解法相同或类似的子问题来求解,便成为递归求解。
例如在求解4!时先求解3!,然后再进一步分解进行求解,这种求解方法也叫做“分治法”。
采用“分治法”进行递归求解的问题需满足三个条件:
-能够将一个问题转变为一个小问题,而新问题和原问题的解法相同或类似。不同的仅仅是处理的对象,并且处理更小且变化时有规律的
-可以通过上述转换而使得问题更加简化
-必须要有一个明确的递归出口,或成为递归边界

  1. 数据结构是递归的
    其数据结构本身具有递归的特性。
    例如,对于链表Node的定义由数据域和指针域next组成,而指针域next是一种指向Node类型的指针,即Node的定义中又用到了其自身。所以链表也是一种递归的数据结构。
void TraverseList(LinkList p){
    //递归终止
    if(p == NULL) 
        return; 
    else{
        // 输出当前节点的数据域
        printf("%d",p->data); 
        //p 指向后继节点继续递归
        TraverseList(p->next);
    }
}
  1. 问题的解法是递归的
    有一类问题,虽然问题本身并没有明显的递归结构,但是采用递归求解比迭代求解更简单,比如Hanoi塔问题,八皇后问题,迷宫问题

递归过程与递归工作栈

一个递归函数,在函数的执行过程中,需要进行多次自我调用。那么思考一下,一个递归函数是如何执行的?
在了解递归函数是如何执行之前,先来了解一下任何的两个函数之间是如何进行调用的;
在高级语言的程序中,调用函数和被调用函数之间的链接与信息交换都是通过栈来进行的。
通常,当在一个函数的运行期间调用另一个函数时,在运行被调用函数之前,系统需要完成三件事情:
-将所有的实参,返回地址等信息调用传递给被调用函数保存;
-为被调用函数的局部变量分配存储空间
-将控制转移到被调用函数入口

而从被调用函数返回调用函数之前,系统同样需要完成三件事:
-保存被调用函数的计算结果;
-释放被调用函数的数据区
-依照被调用函数保存的返回地址将控制移动到调用函数。

当多个函数构成嵌套调用时,按照“先调用后返回”原则,上述函数之间的信息传递和控制转移必须通过“栈”来实现,即系统将整个程序运行时所需要的数据空间都安排在一个栈中,每当调用一个函数时,就在它的栈顶分配一个存储区。每当这个函数退出时,就释放它的存储区。则当前运行时的函数的数据区比在栈顶

一个递归函数的运行过程类似多个函数嵌套调用;只是调用函数和被调用函数是同一个函数.因此,和每次调用相关的一个重要概念是递归函数运行的“层次”,假设调用该递归函数的主函数为第0层,则从主函数调用递归函数进入第1层,从第1层递归调用本函数为进入下一层.即第i+1层.反正退出第1层递归应返回上一层即第i-1层

为了保证递归函数正确执行,系统需要设立一个“递归工作栈“作为整个递归函数运行期间使用的数据存储区.每一层递归所需信息构成一个工作记录,其中包括所有的实参,所有的局部变量以及上一层的返回地址。每进入一层递归,就产生一个新的工作记录压入栈顶.每退出一个递归,就从栈顶弹出一个工作记录,则当前执行层的工作记录必须是递归工作栈栈顶的工作记录,称为“活动记录”

你可能感兴趣的:(004-数据结构与算法-栈和递归的关系)