【重拾C语言】十、递归程序设计

news2024/11/25 1:29:00

目录

前言

十、递归程序设计

10.1 计算n!——递归程序设计

10.2 程序设计实例

10.2.1 汉诺塔

10.2.2 齿轮

10.2.3 组合

10.3 计算算术表达式的值——间接递归

10.4 递归程序执行过程


前言

        递归程序设计是一种编程技术,其中一个函数通过调用自身来解决问题。递归的思想是将大问题划分为更小的子问题,并通过解决子问题来解决原始问题。递归可以在问题的规模较小的情况下,通过不断地调用自身来解决更大规模的问题。递归函数通常包含两个部分:基本情况和递归情况。

  • 基本情况是指问题的规模已经足够小,不再需要进一步的递归调用,可以直接返回结果。这是递归的结束条件。
  • 递归情况是指问题的规模仍然较大,需要通过调用自身来解决更小规模的子问题。递归函数在解决子问题时,会不断地调用自身,直到达到基本情况。

   

十、递归程序设计

10.1 计算n!——递归程序设计

要计算n的阶乘(n!),可以使用递归程序设计。递归计算n的阶乘的思路如下:

  • 基本情况:当n为0或1时,阶乘的结果为1。
  • 递归情况:当n大于1时,n的阶乘可以表示为n乘以(n-1)的阶乘。
#include <stdio.h>

int factorial(int n) {
    if (n == 0) {
        return 1;
    } else {
        return n * factorial(n - 1);
    }
}

int main() {
    int n = 5;
    int result = factorial(n);
    printf("%d! = %d\n", n, result);
    return 0;
}

        函数factorial是递归函数。它将问题划分为计算n乘以(n-1)的阶乘的子问题,并通过递归调用自身来解决子问题,直到达到基本情况。调用这个函数来计算任意正整数n的阶乘,例如factorial(5)将返回120。

10.2 程序设计实例

10.2.1 汉诺塔

        汉诺塔是一个经典的递归问题。它涉及将一堆盘子从一个柱子移动到另一个柱子,每次只能移动一个盘子,并且大盘子不能放在小盘子上面。下面是一个用C语言实现汉诺塔问题的递归函数:

#include <stdio.h>

void hanoi(int n, char source, char destination, char auxiliary) {
    if (n == 1) {
        printf("Move disk 1 from %c to %c\n", source, destination);
        return;
    }
    hanoi(n - 1, source, auxiliary, destination);
    printf("Move disk %d from %c to %c\n", n, source, destination);
    hanoi(n - 1, auxiliary, destination, source);
}

int main() {
    int n = 3;
    hanoi(n, 'A', 'C', 'B');
    return 0;
}

        函数hanoi用来解决汉诺塔问题。它接受四个参数:n表示盘子的数量,source表示源柱子,destination表示目标柱子,auxiliary表示辅助柱子。当n为1时,直接将盘子从源柱子移动到目标柱子。否则,它将递归地将n-1个盘子从源柱子移动到辅助柱子,然后将第n个盘子从源柱子移动到目标柱子,最后将n-1个盘子从辅助柱子移动到目标柱子。

10.2.2 齿轮

10.2.3 组合

        组合是数学中的一个概念,指的是从一个给定的集合中选取一部分元素的方式。想要实现一个计算组合的程序,可以使用递归或迭代的方法:

#include <stdio.h>

int combination(int n, int k) {
    if (k == 0 || k == n) {
        return 1;
    } else {
        return combination(n - 1, k - 1) + combination(n - 1, k);
    }
}

int main() {
    int n = 5;
    int k = 3;
    int result = combination(n, k);
    printf("C(%d, %d) = %d\n", n, k, result);
    return 0;
}

        函数combination用来计算组合。它接受两个参数:n和k,分别表示集合的大小和选取的元素个数。当k等于0或k等于n时,返回1,表示只有一种选取方式。否则,它将递归地计算从n-1个元素中选取k-1个元素的组合数,以及从n-1个元素中选取k个元素的组合数,并将它们相加作为结果。

10.3 计算算术表达式的值——间接递归

        要计算算术表达式的值,可以使用间接递归来实现,间接递归是指多个函数之间相互调用形成的递归关系:

#include <stdio.h>

int expression_value(char* expression);

int factor_value(char* expression) {
    if (expression[0] == '(') {
        return expression_value(expression + 1);
    } else {
        return expression[0] - '0';
    }
}

int term_value(char* expression) {
    int value = factor_value(expression);
    if (expression[1] == '*') {
        value *= term_value(expression + 2);
    }
    return value;
}

int expression_value(char* expression) {
    int value = term_value(expression);
    if (expression[1] == '+') {
        value += expression_value(expression + 2);
    }
    return value;
}

int main() {
    char expression[] = "((2*3)+4)";
    int result = expression_value(expression);
    printf("Expression value: %d\n", result);
    return 0;
}
  • 我们定义了三个函数:expression_valueterm_valuefactor_value,它们之间相互调用形成了间接递归。
    • factor_value函数用来计算因子的值,如果因子是一个括号内的表达式,则调用expression_value函数来计算括号内表达式的值;否则,将字符转换为对应的数字。
    • term_value函数用来计算项的值,首先计算第一个因子的值,然后判断后面是否有乘号,并乘以后面的因子的值。
    • expression_value函数用来计算表达式的值,首先计算第一个项的值,然后判断后面是否有加号,并加上后面的项的值。
  • main函数中,定义一个算术表达式,并调用expression_value函数来计算表达式的值,并打印结果。

10.4 递归程序执行过程

        递归程序的执行过程可以通过堆栈(stack)来理解。当一个函数被调用时,它的局部变量和函数调用的返回地址被压入堆栈。如果函数内部包含递归调用,那么每次递归调用都会将新的局部变量和返回地址压入堆栈。递归的结束条件是达到递归终止条件,此时递归开始回溯,从最后一个递归调用返回到上一个递归调用,然后再返回到更上一层递归调用,直到回到最初的函数调用。

        在递归程序执行过程中,每个递归调用都会占用一些内存空间,并且会在堆栈上创建一个新的帧(frame),包含局部变量和返回地址。当递归调用过多时,可能会导致堆栈溢出(stack overflow)的问题,因为堆栈的大小是有限的。

  • 注意
    • 递归终止条件的设置,否则可能会导致无限递归,使程序陷入死循环。
    • 递归程序还需要注意递归的效率,因为递归调用会带来函数调用的额外开销。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1089897.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Navicat For MySQL使用指南

勾选填充零后的效果&#xff0c;就是不够的位数用零来补齐&#xff01;

Eclipse插件安装版本不兼容问题解决方案——Papyrus插件为例

项目场景: Eclipse Papyrus安装后,没有新建Papyrus工程选项,也没有新建Papyrus Model的选项。 打开Papyrus Model会报错 问题描述 同样的,安装其他插件也是。可能某个插件之前安装是好用的,结果Eclipse的版本更新了,就再也安装不好用了 原因分析: 根本原因是因为包之…

交通 | python网络爬虫:“多线程并行 + 多线程异步协程

推文作者&#xff1a;Amiee 编者按&#xff1a; 常规爬虫都是爬完一个网页接着爬下一个网页&#xff0c;不适应数据量大的网页&#xff0c;本文介绍了多线程处理同时爬取多个网页的内容&#xff0c;提升爬虫效率。 1.引言​ 一般而言&#xff0c;常规爬虫都是爬完一个网页接着…

【MySql】7- 实践篇(五)

文章目录 1. 加锁规则1.1 案例一&#xff1a;等值查询间隙锁1.2 案例二&#xff1a;非唯一索引等值锁1.3 案例三&#xff1a;主键索引范围锁1.4 案例四&#xff1a;非唯一索引范围锁1.5 案例五&#xff1a;唯一索引范围锁 bug1.6 案例六&#xff1a;非唯一索引上存在"等值…

TLS 详解

目录 TLS 定义HTTPS HTTP over TLS.加密记录层分片 (Fragmentation)记录压缩和解压缩 (Record compression and decompression)空或标准流加密 (Null or standard stream cipher)CBC 块加密 (分组加密)记录有效载荷保护 (Record payload protection)密钥计算 (Key calculation…

【C++初阶】关键字命名空间缺省函数函数重载入门必看!!!超详解!!!

主页点击直达&#xff1a;个人主页 我的小仓库&#xff1a;代码仓库 C语言偷着笑&#xff1a;C语言专栏 数据结构挨打小记&#xff1a;初阶数据结构专栏 Linux被操作记&#xff1a;Linux专栏 LeetCode刷题掉发记&#xff1a;LeetCode刷题 算法&#xff1a;算法专栏 C头…

解锁互联网安全的新钥匙:JWT(JSON Web Token)

目录 前言 一、JWT简介 1. 什么是JWT&#xff1f; ​编辑 2. JWT的工作原理 3.JWT如何工作的 4. JWT的优势 5. 在实际应用中使用JWT 6.传统Session和JWT认证的区别 6.1.session认证方式 6.2.JWT认证方式 7.基于Token的身份认证 与 基于服务器的身份认证 二、JWT的…

一文带你快速上手MySQL8窗口函数,实现更高效的数据处理

文章目录 MySQL8窗口函数前言窗口函数相关概念介绍窗口函数分区介绍 窗口函数的使用语法介绍实战演练示例一&#xff1a;聚合函数示例二&#xff1a;排名函数示例三&#xff1a;偏移函数示例四&#xff1a;分布函数示例五&#xff1a;首尾函数示例六&#xff1a;其它函数 总结 …

GIS小技术分享(一):python中json数据转geojson或者shp

1.环境需求 geopandspandasshapelyjsonpython3 2.输入数据&#xff08;path字段&#xff0c;线条&#xff09; [{"id": "586A685D568311B2A16F33FCD5055F7B","name": "普及江","path": "[[116.35178835446628,23.57…

NeuroImage | 右侧颞上回在语义规则学习中的作用:来自强化学习模型的证据

在现实生活中&#xff0c;许多规则的获取通常需要使用语言作为桥梁&#xff0c;特别是语义在信息传递中起着至关重要的作用。另外&#xff0c;个体使用的语言往往具有明显的奖励和惩罚元素&#xff0c;如赞扬和批评。一种常见的规则是寻求更多的赞扬&#xff0c;同时避免批评。…

十八、【模糊工具组】

文章目录 模糊工具锐化工具涂抹工具 模糊工具 使用模糊工具可以对图像边缘以及其他一部分区域进行编辑&#xff0c;可以使其变得模糊&#xff0c;从而更加突出主体&#xff1a; 锐化工具 锐化工具跟模糊工具是相反的一个工具啊&#xff0c;锐化工具主要是增强图像的颗粒度&am…

20基于MATLAB的车牌识别算法,在环境较差的情景下,夜间识别度很差的车牌号码可以精确识别出具体结果,程序已调通,可直接替换自己的数据跑。

基于MATLAB的车牌识别算法&#xff0c;在环境较差的情景下&#xff0c;夜间识别度很差的车牌号码可以精确识别出具体结果&#xff0c;程序已调通&#xff0c;可直接替换自己的数据跑。 20matlab车牌识别 (xiaohongshu.com)

大数据Doris(十):添加BE步骤

文章目录 添加BE步骤 一、使用mysql连接 二、​​​​​​​添加be

npm安装依赖报错npm ERR! code ENOTFOUND npm ERR! errno ENOTFOUND、npm run dev报错记录

npm安装依赖报错npm ERR! code ENOTFOUND npm ERR! errno ENOTFOUND_得我所得&#xff0c;爱我所爱的博客-CSDN博客npm安装依赖报错今天在学习webpack的时候&#xff0c;在使用npm install来安装一个局部的webpack时候&#xff0c;报出一下错误:npm ERR! code ENOTFOUNDnpm ERR…

centos7部署Nginx和RabbitMQ

文章目录 Nginx安装部署【简单】简介安装 RabbitMQ安装部署【简单】简介安装 Nginx安装部署【简单】 简介 Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器&#xff0c;同时也提供了IMAP/POP3/SMTP服务。Nginx可以托管用户编写的WEB应用程序成为可访问的网页服务&am…

Grafana 10 新特性解读:体验与协作全面提升

作者&#xff1a;徽泠(苏墨馨) 为了庆祝 Grafana 的 10 年里程碑&#xff0c;Grafana Labs 推出了 Grafana 10&#xff0c;这个具有纪念意义的版本强调增强用户体验&#xff0c;使各种开发人员更容易使用。Grafana v10.0.x 为开发者与企业展示卓越的新功能、可视化与协作能力&…

精品Python的计算机科学研究话题管理系统-可视化大屏

《[含文档PPT源码等]精品Python的计算机科学研究话题管理系统设计与实现-爬虫》该项目含有源码、文档、PPT、配套开发软件、软件安装教程、项目发布教程等&#xff01; 软件开发环境及开发工具&#xff1a; 开发语言&#xff1a;python 使用框架&#xff1a;Django 前端技术…

时间序列分析基础篇

**时间序列分析&#xff08;time series analysis&#xff09;是量化投资中的一门基本技术。时间序列是指在一定时间内按时间顺序测量的某个变量的取值序列。**比如变量是股票价格&#xff0c;那么它随时间的变化就是一个时间序列&#xff1b;同样的&#xff0c;如果变量是股票…

【树莓派/入门】1.69inch LCD屏幕的连接与测试

说在前面 树莓派版本&#xff1a;4bLCD模块&#xff1a;MAX30102树莓派系统&#xff1a;Linux raspberrypi 5.15.76-v8 #1597 SMP aarch64 GNU/Linuxpython版本&#xff1a;3.9.2买回来发现不是触摸屏&#xff0c;瞎了 模块详情 某雪的1.69inch LCD模块&#xff0c;包含杜邦线…

10月13日星期五今日早报简报微语报早读

10月13日星期五&#xff0c;农历八月廿九&#xff0c;早报微语早读分享。 1、我国2022年出生人口956万&#xff0c;三孩及以上占比为15%&#xff1b; 2、九部门&#xff1a;支持针对新能源汽车等发展国际级、国家级汽车赛事&#xff1b; 3、外交部&#xff1a;目前已确认3名中…