递归函数设计

一.递归函数的设计

递归函数的设计主要是三步:

1.给定该函数一个明确的语义

2.实现边界条件时的程序逻辑

3.假设递归函数调用返回值正确,实现本层函数逻辑

其中,最重要的是第一步,下面看几个例子来感受递归函数的设计

二.例题

一.路飞吃桃

#include <stdio.h>
int f(int x){
    if(x == 1) return 1;
    return (f(x - 1) + 1) * 2;
}
int main() {
    int n;
    scanf("%d", &n);
    printf("%d", f(n));
    return 0;
}

二.弹簧板

#include <stdio.h>
#define max_n 100000
int f(int i, int *p, int n){
    if(i >= n) return 0;
    return f(i + p[i], p, n) + 1;
}
int main() {
    int n, cnt = 0;
    scanf("%d", &n);
    int arr[max_n + 5];
    for(int i = 0; i < n; i++){
        scanf("%d", &arr[i]);
    }
    printf("%d", f(0, arr, n));
    return  0;
 }

三.递归实现指数型枚举

#include <stdio.h>
void printf_one_result(int x, int *p){
    for(int i = 0; i <= x; i++){
        if(i) printf(" ");
        printf("%d", p[i]);
    }
    printf("\n");
    return ;
}
void f(int i, int j, int x, int *p){ //求从下标为i的位置开始的指数型枚举,j表示当前位置所能枚举的最小值,x表示枚举上限,p指针指向存数据的数组 
    if(j > x) return ;//当j为上限时,i位置就不能继续向后枚举
    for(int k = j; k <= x; k++){
        p[i] = k;
        printf_one_result(i, p);//当i位置存k时,输出从0到i的数据
        f(i + 1, k + 1, x, p);//利用递归,进行i+1位置的指数型枚举
    }
    return ;
}
//核心思想就是枚举每个位置所能取得值,前提条件时由其前一个位置的值提供
int main() {
    int n;
    scanf("%d", &n);
    int arr[10];
    f(0, 1, n, arr); 
    return 0;
}

四.递归实现组合型枚举

#include <stdio.h>
void printf_one_result(int m, int *p) {
    for(int i = 0; i < m; i++){
        if(i) printf(" ");
        printf("%d", p[i]);
    }
    printf("\n");
    return ;
}
void f(int i, int j, int n, int m, int *p){
    if(i == m){
        printf_one_result(m, p);
        return ;
    }
    for(int k = j; k <= n && m - i - 1 <= n - k; k++){
        p[i] = k;
        f(i + 1, k + 1, n, m, p);
    }
    return ;
}
//组合数枚举
int main() {
    int n, m;
    scanf("%d%d", &n, &m);
    int arr[10];
    f(0, 1, n, m, arr);
    return 0;
}

五.递归实现排列型枚举

#include <stdio.h>
void printf_one_result(int *p1, int n){
    for(int i = 0; i < n; i++){
        if(i) printf(" ");
        printf("%d", p1[i]);
    }
    printf("\n");
    return ;
}
void f(int i, int n, int *p1, int *p2){
    if(i == n){
        printf_one_result(p1, n);
        return ;
    }
    for(int k = 1; k <= n; k++){
        if(p2[k]) continue;
        p1[i] = k;
        p2[k] = 1;
        f(i + 1, n, p1, p2);
        p2[k] = 0; //当程序枚举完i+1位之后的排列后,回溯到本层循环时,将当前位置的k回收
    }
    return ;
}
int main() {
    int n;
    scanf("%d", &n);
    int arr[10], flag[10] = {0};
    f(0, n, arr, flag);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值