H递归函数.go

前言:递归函数是一种强大而又充满魅力的编程技巧。它就像是一面神奇的镜子,函数在其中能够调用自身的倒影,从而以一种简洁而优雅的方式解决许多复杂的问题。 

目录

一、递归函数是啥玩意儿

二、递归函数的优缺点

优点

缺点

三、递归函数能干啥

四、递归函数咋优化

五、递归函数经典案例 - 汉诺塔问题

总结


一、递归函数是啥玩意儿

递归函数说白了,就是函数自己调用自己。不过,咱可不能让函数这么一直调用下去没完没了,不然程序就 “跑偏” 了。所以得给它设个 “停止信号”,也就是终止条件。一到这个条件,函数就老实停下来,不再调自己啦,然后把之前算出来的结果一层一层地返回去。

举个超简单的例子,算阶乘就特别适合用递归函数。阶乘就是把一个正整数 n 和所有比它小的正整数都乘起来,像 5! = 5 × 4 × 3 × 2 × 1。咱用递归的思路想,其实就是 n! = n × (n - 1)! ,那咱就让函数自己调自己,把问题越变越小,直到变成 1! = 1,这时候就让函数停住返结果。

package mainimport "fmt"func factorial(n int) int {if n == 1 { // 咱的终止条件就这儿,要是 n 是 1,就返 1return 1}return n * factorial(n-1) // 这里函数就开始调自己啦,看不看懂?
}func main() {fmt.Println(factorial(5)) // 试一试,看看会不会返 120 呢
}

看看,这代码是不是超简洁?就像把问题一层层剥开,找到最里面的核心,然后再一层层包回去,把结果算出来。

二、递归函数的优缺点

优点

  • 代码简洁 :递归函数能把复杂问题拆成小问题,代码看着就清爽多了。比如算斐波那契数列(斐波那契数列就是从 0 和 1 开始,后面的数都是前两个数的和),递归写法就很简单:

package mainimport "fmt"func fibonacci(n int) int {if n <= 1 {return n}return fibonacci(n-1) + fibonacci(n-2) // 自己调自己,把问题拆小
}func main() {fmt.Println(fibonacci(10)) // 算一算第 10 个斐波那契数
}

缺点

  • 性能问题 :递归调用自己会搞出好多新的栈帧(栈帧就是函数调用时在内存里占的小窝),要是调用太多次,就会把栈给搞溢出,程序就直接 “扑街” 了。而且像斐波那契数列的简单递归写法,会算好多重复的东西,效率很低。

  • 调试困难 :递归函数调来调去,调试的时候得跟着好多层函数调用,搞起来有点麻烦。

三、递归函数能干啥

  • 树或图的遍历 :比如遍历文件系统里的目录,递归地把每个文件夹和文件都瞅一遍:

package mainimport ("fmt""path/filepath"
)func traverseDir(path string) {entries, err := filepath.Glob(filepath.Join(path, "*"))if err != nil {fmt.Println("哎呀,出错了:", err)return}for _, entry := range entries {if info, err := filepath.Stat(entry); err == nil && info.IsDir() {fmt.Println("哇,这是个文件夹:", entry)traverseDir(entry) // 递归遍历子文件夹} else {fmt.Println("嘿,这是个文件:", entry)}}
}func main() {traverseDir("./testdir") // 假设当前目录下有个叫 testdir 的文件夹
}
  • 深度优先搜索(DFS) :在迷宫求解、八皇后这种问题里都能用上,像是在迷宫里一直往深处走,走不通了再回来换条路。

四、递归函数咋优化

  • 记忆化 :对于斐波那契数列,可以用记忆化避免重复算,搞个 “小本本” 把算过的结果记下来:

package mainimport "fmt"func fibonacci(n int, memo map[int]int) int {if val, exists := memo[n]; exists { // 先瞅瞅算过没return val}if n <= 1 {memo[n] = n} else {memo[n] = fibonacci(n-1, memo) + fibonacci(n-2, memo)}return memo[n]
}func main() {memo := make(map[int]int)fmt.Println(fibonacci(10, memo)) // 算一算第 10 个斐波那契数
}
  • 尾递归优化 :把递归调用放在函数的最后一步,有些编译器会把它优化成循环,避免把栈搞崩。比如算阶乘的尾递归写法:

package mainimport "fmt"func factorial(n int, acc int) int {if n == 0 {return acc}return factorial(n-1, n*acc) // 尾递归调用
}func main() {fmt.Println(factorial(5, 1)) // 算一算 5 的阶乘
}

五、递归函数经典案例 - 汉诺塔问题

汉诺塔是个超经典的递归问题。有三根柱子 A、B、C,A 上面有 n 个盘子,按从大到小叠着。要求把所有盘子都移到 C 上,每次只能移一个,还不能把大的盘子放在小的上面。

package mainimport "fmt"func hanoi(n int, from, aux, to string) {if n == 1 {fmt.Printf("把盘子 1 从 %s 移到 %s\n", from, to)return}hanoi(n-1, from, to, aux)      // 把 n-1 个盘子从 from 移到 auxfmt.Printf("把盘子 %d 从 %s 移到 %s\n", n, from, to) // 移最后一个盘子hanoi(n-1, aux, from, to)      // 把 n-1 个盘子从 aux 移到 to
}func main() {hanoi(3, "A", "B", "C") // 算一算 3 个盘子咋移
}

这段代码把问题拆成把 n-1 个盘子移来移去的子问题,最后就解决了整个汉诺塔问题。

总结

递归函数就是这么个既厉害又有点小脾气的工具。宝子们要是刚入门别怕,多写写多练练,理解了它的终止条件和调用过程,就能轻松用它搞定好多复杂问题。不过写的时候得注意性能问题,要是函数调用太多,栈就不够用了,必要时就用优化技巧。相信宝子们只要肯花时间,很快就能掌握递归函数的精髓,让它变成自己编程路上的好帮手。

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

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

相关文章

软件功能测试的测试标准

一、软件功能测试行业标准概述 软件功能测试行业标准是规范软件测试流程、方法、工具及人员资质的准则&#xff0c;是确保软件产品的功能性、可靠性、易用性等质量特性符合用户需求。这些标准不仅为测试人员提供了明确的指导&#xff0c;也为软件产品的质量控制提供了有力保障。…

EchoEar(喵伴):乐鑫发布与火山引擎扣子联名 AI 智能体开发板

随着生成式人工智能技术的快速发展&#xff0c;大语言模型 (LLM) 正逐步成为推动智能设备升级的核心力量。乐鑫科技携手火山引擎扣子大模型团队&#xff0c;共同推出智能 AI 开发套件 —— EchoEar&#xff08;喵伴&#xff09;。该套件以端到端开发为核心理念&#xff0c;构建…

图像特征检测算法SIFT

SIFT&#xff08;Scale - Invariant Feature Transform&#xff0c;尺度不变特征变换&#xff09;是一种计算机视觉领域的特征提取算法&#xff0c;具有重要的地位和广泛的应用。 算法原理 构建高斯金字塔 &#xff1a; 为了实现多尺度检测&#xff0c;SIFT 算法会构建高斯金…

光纤通道收发器:市场洞察、技术演进与未来机遇

一、引言 在数字化浪潮席卷全球的当下&#xff0c;数据存储与传输的需求呈爆发式增长。光纤通道收发器作为高速、可靠数据存储网络&#xff08;如存储区域网络 SAN&#xff09;中的关键组件&#xff0c;发挥着至关重要的作用。它通过光纤实现服务器、存储设备和交换机之间的数…

candence17.4如何设置两个焊盘之间在TOP与BOTTOM可以存在两根线

为什么要走两根线&#xff1f; 为了过大电流&#xff0c;有时候就需要我们在TOP、BOTTOM两个面走线&#xff0c;同时开窗&#xff0c;然后通过加锡的方式增加过流能力&#xff1b; 当然由于两面都有导线&#xff0c;必然会存在过孔&#xff0c;而过孔的过流能力不仅与过孔孔径…

Dify:参数调节,让LLM从能用到好用的机制

前言 随着大语言模型(LLM)在文本生成、智能对话、技术问答等前沿领域的深度渗透&#xff0c;参数精细化调节已成为开发者驾驭 AI 能力的核心必修课。 本文将系统的解释温度(Temperature)、核采样(Top - P)、截断采样(Top - K)等关键参数的底层作用机制&#xff0c;结合多种场景…

防抖不同的实现

防抖&#xff08;Debounce&#xff09;&#xff1a;在事件被触发后&#xff0c;延迟一段时间再执行函数。如果在延迟期间事件再次被触发&#xff0c;则重新计时。常用于搜索框输入、窗口大小调整等场景。 1.不安装任何依赖和库&#xff0c;编写一个防抖的函数 在utils里面增加…

MySQL 数据库索引详解

一、索引是什么&#xff1f;能干嘛&#xff1f; 类比理解&#xff1a;索引就像书的目录。比如你想查《哈利波特》中 “伏地魔” 出现的页数&#xff0c;不用逐页翻书&#xff0c;直接看目录找关键词就行。数据库里的索引就是帮你快速找到数据的 “目录”。 核心作用&#xff…

【620公司工作记录】

已有数据汇总 好的,完全同意。在编写新代码之前,清晰地盘点我们手中已有的“弹药”是至关重要的一步。 根据您提供的 test/20250610_88_100mm_frame_000.csv 文件头,我来为您完整地解析一下我们当前拥有的全部数据字段。我们的数据是以“行”为单位组织的,每一行都代表一…

SpringBoot 集成Caffeine实现一级缓存

SpeingBoot 集成Caffeine实现一级缓存使我们经常遇到的场景。今天我们具体分享一下&#xff1a; 首先 Caffeine 作为一级缓存&#xff0c;它是 Spring 5.x 默认的本地缓存实现&#xff0c;性能优于 Guava Cache&#xff0c;且支持过期时间设置。缓存执行的流程图如下&#xff…

中科米堆3D自动扫描检测系统三维数字化智能解决方案

3D自动扫描检测系统基于先进的光学、激光或结构光等测量技术&#xff0c;能够快速、准确地获取工件的三维几何数据。在检测过程中&#xff0c;系统通过向被测工件投射特定的光模式&#xff0c;利用高分辨率相机捕捉工件表面的反射光信息&#xff0c;再经过复杂的算法处理&#…

Unity3d中使用Mirror进行自定义消息通信

一、服务端&#xff1a; 1.创建服务端脚本MyServer.cs 继承自NetworkManager类 using Mirror; using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI;public class MyServer : NetworkManager {[Header(&quo…

Odoo 18 固定资产管理自动化指南

如何在Odoo 18中实现资产管理自动化 1. 创建资产模型实现资产管理自动化 使用 Odoo 18 的会计模块&#xff0c;资产的创建和确认可轻松实现自动化。这将使资产管理变得更加简单高效。使用资产自动化功能&#xff0c;一旦验证相关产品的供应商账单&#xff0c;Odoo将自动生成并…

如何轻松地将音乐从 iPhone 传输到 Mac?

想把音乐从 iPhone 传输到 Mac 吗&#xff1f;这很常见&#xff0c;无论你是想更换设备、备份收藏&#xff0c;还是只想在更大的屏幕上欣赏喜爱的歌曲。幸运的是&#xff0c;有 6 种有效的方法可以完成这项工作&#xff0c;具体取决于你喜欢使用的工具。让我们开始吧。 第 1 部…

人工智能——解读AI智慧课堂系统解决方案【附全文阅读】

该文档是 AI 智慧课堂系统解决方案,聚焦教育信息化需求,通过 AI 技术与教学深度融合,解决传统课堂考勤效率低、资源管理难、分析不精准等问题。 方案以课堂为核心,构建 “背景分析 - 方案设计 - 优势价值” 框架,技术架构涵盖教师摄像机、学生抓拍机、智能录播主机等设备,…

使用Nginx的RTMP模块进行直播流转HLS时,处理和预防`.ts`文件过多

当使用Nginx的RTMP模块进行直播流转HLS时,如果长时间运行或处理大量流媒体内容,可能会遇到.ts文件累积过多的问题。这不仅会占用大量的磁盘空间,还可能影响系统性能。以下是一些处理和预防.ts文件过多的方法: 1. 配置HLS清理 Nginx RTMP模块允许配置HLS片段的过期时间,这…

结构体解决冒泡排序

设计英雄的结构体 //1、设计结构体 struct Hero {string name;//姓名int age;//年龄string sex;//性别 };创建英雄的数组 //2、创建数组存放英雄 struct Hero Array[5] {{"刘备", 34 ,"男"},{"关羽", 45 ,"男"},{"张飞",…

spring-webmvc @RequestParam 典型用法

典型用法 基本使用 HTTP请求参数绑定到方法参数 GetMapping("/users") public String getUsers(RequestParam String name) {return "Hello, " name; }请求&#xff1a;/users?nameJohn 输出&#xff1a;Hello, John-----GetMapping("/filter&qu…

AntDesignPro前后端权限按钮系统实现

目录 Ant Design Pro 后端接口权限按钮系统 系统架构图 前端实现 权限按钮组件 (AuthButton.tsx) 权限钩子 (useAccess.ts) 权限服务 (permission.ts) 产品列表页面 (ProductList.tsx) 后端接口设计 (Node.js Express 示例) 权限接口控制器 (permissionController.js…

RAG工程落地:处理文档中表格数据

在 RAG&#xff08;Retrieval-Augmented Generation&#xff09;工程落地过程中&#xff0c;处理文档中的表格数据 是一个非常重要但复杂的问题&#xff0c;特别是针对技术文档、报告、论文等结构化强的资料。比如PDF文档里的表格数据&#xff0c;如下&#xff1a; RAG处理表格…