算法设计与分析复习(一)递归

 资料:
    学校ppt
  《计算机算法设计与分析》(第五版)
   五分钟学算法
   leetcode

递归算法实现机制

一、递归的背景

1、数学中的递归
类似于求解数列的递推公式:
在这里插入图片描述
2、生活中的递归
3、有趣的小故事理解递归
从前有座山,山里有座庙的故事
4、计算机中的递归
常见的递归数据结构:单链表、二叉树等
5、递归的重要性

  • 递归是程序设计中重要而有效的思想
  • 递归是运筹学、决策论和图论等领域的重要内容
  • 递归的特点:直观、有效
二、递归的实现机制

1、定义:一个过程直接地或间接地调用自己的过程是递归的过程。
2、递归的实质实际上就是能够把一个大问题分解成比它小点的问题,然后我们拿到了小问题的解,就可以用小问题去构造大问题的解。

在这里插入图片描述
在这里插入图片描述

子程序实现原理

首先从一般的直接调用一次和n次子程序的形式讨论:
(无嵌套)
在这里插入图片描述
(有嵌套)
在这里插入图片描述
其次看一下值回传方式:

  • 子程序调用时,用栈的方式管理调用子程序时的返回地址。
  • 数据传送通过参数或全局变量
  • 为子程序的局部变量、形参分配存储空间,并放在栈顶

在这里插入图片描述
应该是一个在实参上直接修改,另一个是使用一个新的存储空间,然后把实参值copy过来,在新的存储空间上对原来的实参值进行修改,然后再将修改后的新值赋值给实参。
== 本章讨论的都是采用两次值传送方式==
子程序调用的内部操作
在这里插入图片描述
执行调用时相当于先保存下降进程的现场-为上升进程的局部变量开辟空间-传入参数-转入上升进程执行
执行返回操作时先保存到回传变量-弹出地址并返回该地址-回传变量值送到相应位置

递归程序实现原理

在这里插入图片描述
还有间接调用,递归出口

在这里插入图片描述
绿色的是执行到递归的部分之前执行的函数,黄色部分是到递归出口之后层层返回之后执行的内容,返回到上一个是得在下面黄色部分执行完才能返回到再上一级。
在这里插入图片描述
⚠️栈元素由现场信息和参数构成

递归算法设计

一、递归设计需满足的条件

在这里插入图片描述
这三点应该时刻铭记!!!

二、递归求解的通用表现形式

在这里插入图片描述

1、常见的问题规模和相关参数的表现形式
2、相关解读
  • 简单操作即是递归出口将要执行的操作
  • call P中参数表反应问题规模的参数应该是down
  • 在call P结束之后会得到规模变小的问题的解和相关信息结合得到的整个问题的解
三、递归的几个典型例子
1、简单的0/1背包问题

在这里插入图片描述
㊗️0/1背包问题对于每个物品仅存在两种情况:取:1/不取:0
不能取一部分
⚠️要求是放入背包的质量之和正好为m,所以这个问题要么有解,要么无解
分析过程:
(一)
1、考察物品只有一个的时候背包的容量n=1
2、划分成前n-1个和第n个,如何降低规模
(二)
1、如果第n个物品超过容量,则第n个物品一定不能返回,那么考察范围就缩小到n-1

knap(m,n-1);

这时候knap(m,n-1)的值就是knap(m,n)的值,如果n-1的成功,n也成功
2、如果第n个物品小于容量,也分两种情况

(1)knap(bag-m[n],n-1);
(2)knap(bag,n-1);

也是按照选择还是不选择进行
实现:


#include <iostream>
using namespace std;
bool judge(int bag,int n,int* m);
int main(){
    int bag = 20;
    int n = 5;
    int m[5]={3,5,8,9,10};
    cout<<judge(bag, n-1, m)<<endl;
    return 0;
}
bool judge(int bag,int n,int* m){
    if(bag==m[n])
        return true;
    if(n>0){
        if(bag>m[n]){
            if(!judge(bag, n-1, m))
            {
                return judge(bag-m[n], n-1, m);
            }
            else{
                return true;
            }
        }
        else{
            return judge(bag, n-1, m);
            }
    }
       return false;
}

在当前物品的质量小于背包可装的质量时,两种情况有一个if判断,在一个不成功的情况下才选择另外一个执行;而且递归出口是因为每一个物品都有可能整体的放入背包将其装满。

2、棋子移动问题

在这里插入图片描述
在这里插入图片描述

int main(){
    int n;
    cout<<"the number of the chess :"<<endl;
    cin>>n;
    int chess[2*n+1];
    for(int i=1;i<=n;i++)
    {
        chess[i]=0;
        chess[i+n]=1;
    }
    for(int i=1;i<=2*n;i++)
    {
        cout<<chess[i]<<" ";
    }
    cout<<endl;
    sort(chess,n);
    for(int i=1;i<=2*n;i++)
    {
        cout<<chess[i]<<" ";
    }
    cout<<endl;   
    return 0;
}
void exchange(int& a,int& b){
    int temp = a;
    a=b;
    b=temp;
}
void sort(int* chess,int n){
    if(n==1)
    {
        
        return ;
    }
    else{
        exchange(chess[n+1], chess[2*n]);
        exchange(chess[n], chess[2*n-1]);
        sort(chess,n-1);
    }
}

在这里插入图片描述
在这里插入图片描述

递归算法的时间复杂性分析

在这里插入图片描述
递归的时间复杂性可以直接通过递推公式得到。
时间复杂度:随着自变量的增长,算法所需时间的增长情况
大O表示法表示的是一个算法在worst case的表现情况:在这里插入图片描述
空间复杂度分析
一般书上写的都是:算法运行期间所占用的所有内存空间。在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

小结

在这里插入图片描述

教材递归与分治策略课后习题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值