从栈的角度理解递归

1.常使用递归的一些情况:

1.定义是递归的:

eg阶乘函数

这种情况常使用 分治法:把复杂问题分解成几个相对简单且接法相同或类似的子问题

条件是:子问题更简单、处理对象更小、且有边界

一般形式为:

void p(参数){

    if(递归结束条件成立){

        可直接求解;

    }else{

        p(较小的参数)

    }

}

2.数据结构是递归的:

eg链表:结点LNode由数据域和指针域组成,而指针域是指向下一个LNode类型的指针

打印链表

//不使用递归

void display(link *p) {

    linktemp = p;//temp指针指向头结点

    //只要temp指针指向的结点的next不是Null,就执行输出语句。

    while (temp->next) {

        temp = temp->next;

        printf("%d "temp->elem);

    }

    printf("\n");

}

// 使用递归

void display2(link *p){

    linktemp = p;

    if(temp->next==NULL){

        printf("\n");

        return ;

    }else{

        printf("%d",temp->elem);

        display2(temp->next);

    }

}

// 当if递归条件结束时,只返回空,可以化简

void display3(link *p){

    link *temp=p;

    if(temp){

        printf("%d",temp->elem);

        display2(temp->next);       

    }

}

 

3.问题的解法是递归的

Eg

 Hanoi塔(汉诺)问题描述: 

有n个盘子在A处, 盘子从大到小排列,最上面的盘子最小。

现在要把这n个盘子从A处搬到C处,可以在B处暂存,

但任何时候都不能出现大盘子压在小盘子上面的情况。 

#include <iostream>

using namespace std;

void move(int n,char A,char C){

    // 把第n个盘子从A移动到C

    cout<<n<<","<<A<<","<<C<<endl;

}

// 将1到n个盘子,从A移动C,B作为过渡

void Hanoi(int n,char A,char B,char C){

    if(n==1){

        // 当n=1时直接一步操作即可

        move(1,A,C);

    }else{

        // 当n>=2时的操作具有相似性,都需进行以下3步:

        // 1,递归,将1到n-1个盘子,从A移动B,C作为过渡

        Hanoi(n-1,A,C,B);

        // 2,将第n个盘子从A移动到C,必须把最大的放在最底下

        move(n,A,C);

        // 3,递归,将1到n-1个盘子,从B移动C,A作为过渡

        Hanoi(n-1,B,A,C);

    }

}

int main()

{

    int n;

    cin>>n;

    char A='A',B='B',C='C';

    Hanoi(n,A,B,C);

    return 0;

}

2.栈与递归

1.在运行一个函数期间调用另一个函数:

在运行被调用函数之前,系统需要完成三件事:

1、将所有的实参、返回地址等信息传递给被调函数保存。

2、为被调函数的局部变量分配存储区。

3、将控制转移到被调函数入口。

而从被调用函数返回调用函数之前,系统也要完成三件事:

1、保存被调函数的计算结果。

2、释放被调函数的数据区。

3、依照被调函数保存的返回地址将控制转移到调用函数。

2.通过栈来解释:

1,当多个函数构成嵌套调用(例如递归函数)时,按照“先调用后返回”的原则

2,上述函数之间信息传递和控制转移必须通过“栈”来实现

3,系统将整个程序的运行空间安排在一个栈中。

     每当调用一个函数时,就在栈顶分配一个存储区,(入栈)

     每当一个函数退出后,释放它的存储区,(出栈)

     所以当前运行的函数的数据区一定在栈顶。

活动记录:函数被调用时分配的存储空间,相当于栈的一个结点

Main()

f(4)

f(3)

f(2)

f(1)

f(0)

->

<-

0,栈底

1

2

3

4

5,栈顶元素

3.递归算法的效率分析

1.时间复杂度

不同问题的时间复杂度不一样

迭代法

递归算法时间复杂度分析_AcceptedLin的博客-CSDN博客_递归的时间复杂度怎么算

eg汉诺塔问题

2.空间复杂度

S(n)=O(f(n)),f(n)为递归工作栈中,工作记录个数与问题规模n的函数关系

4.利用栈将递归转化为非递归

可以利用栈的特点,写出相应的非递归算法

这样做主要是为了防止:当递归次数足够大时,会导致函数栈溢出而死机

PS:很多情况下,代码的易维护性是一个比性能开销更加重要的因素,因此,只要实际应用中不会造成函数栈溢出,可以采用递归函数法。

 理解递归的本质:递归与栈_bobbypollo的专栏-CSDN博客

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值