C语言递归算法实现经典例题

news2024/11/19 16:42:38

一.递归

1.什么是递归

递归是一种编程技术,它通过在函数内部反复调用自身来解决问题。当一个程序调用自己时,这就称为递归调用。递归可以有助于简化某些算法的实现和理解。在递归过程中,每个调用都会将一些数据保存在栈上,直到递归结束后才能被处理并弹出栈。

递归通常有两个部分:基本情况和递归情况。基本情况是在函数执行之前判断是否需要递归,如果不需要,则直接返回结果。递归情况是函数需要递归时,它会调用自身,但是传入的参数通常会有所不同,以便最终能够达到基本情况而结束递归。

虽然递归可以使代码更加简洁,但是需要注意的是,在一些情况下,它可能会导致性能问题或者栈溢出等问题。因此,在编写递归代码时,需要仔细考虑算法的边界条件和递归深度等因素。

2.递归函数

递归函数是一种函数,它在其定义中调用自身。通常情况下,递归函数包含两个部分:基本情况和递归情况。

基本情况是指在递归函数中需要判断是否需要终止递归的条件。当满足这个条件时,递归就会停止。

递归情况是指在递归函数中需要调用自身的情况。在每次调用时,函数的参数都应该有所不同,以便最终能够达到基本情况而停止递归。

递归函数通常用于处理树形结构、图形结构或其他类型的嵌套结构数据。例如,在二叉树中查找某一个值,就可以使用递归函数来实现。

3.说明

虽然递归算法比较简单,但是它是一种编程的思想,在解决部分问题时,它非常适用。并且他一般作为一种工具,搭配其他思想一起使用。它是C语言数据结构与算法中最简单的算法,这里举几个例子来学会使用它。

二.斐波那契数列

1.问题描述

斐波那契数列是一个经典的数学问题,由0和1开始,之后的每一项都是其前面两项的和。也就是说,斐波那契数列的前几个数是:0、1、1、2、3、5、8、13、21、34……依次类推。

斐波那契数列在自然界中有很多应用,比如植物的叶子排列、蜂窝的构造等等。除此之外,在计算机科学领域内,斐波那契数列也有着广泛的应用,例如在排序算法、密码学等领域。

斐波那契数列的通项公式是:F(n) = F(n-1) + F(n-2),其中F(0)=0,F(1)=1。根据这个公式可以使用递归函数或循环语句来实现求斐波那契数列的第n项。

2.思路

像这种可以求出通项公式的数列是我们平时典型的递归函数运用,通项公式可以定义为函数,它的第一个值一般是我们的递归函数出口。所谓递归函数的出口就是结束递归的标志。

现在理清思路后,我们来用代码完成求斐波拉契数列的第n项:

3.C语言代码

#include <stdio.h>

int fibonacci(int n) {
    if (n == 0)
        return 0;
    else if (n == 1)
        return 1;
    else
        return fibonacci(n - 1) + fibonacci(n - 2);
}

int main() {
    int num, i;
    printf("Enter the number of terms: ");
    scanf("%d", &num);
    printf("Fibonacci series terms are:\n");
    for (i = 0; i < num; i++) {
        printf("%d ", fibonacci(i));
    }
    printf("\n");
    return 0;
}

三.汉诺塔

1.问题描述

该问题的主要材料包括三根高度相同的柱子和一些大小及颜色不同的圆盘,三根柱子分别为起始柱A,辅助柱B及目标柱C。

**操作规则:**每次只能移动一个盘子,并且在移动过程中三根杆上都始终保持大盘在下,小盘在上,操作过程中盘子可以置于任意杆上。

wUhV.jpg

2.分析

汉诺塔是一种经典的递归问题,它涉及到将一组不同大小的圆盘从一个柱子移动到另一个柱子。以下是汉诺塔的具体过程:

  1. 将所有圆盘从起始柱子上除最下面一个圆盘之外的其他圆盘全部移动到中间柱子。
  2. 将最下面的圆盘从起始柱子上移动到目标柱子上。
  3. 将中间柱子上除了最下面的圆盘之外的其他圆盘全部移动到目标柱子上。

在完成这三个步骤时,需要遵守以下规则:

  1. 一次只能移动一个圆盘。
  2. 大圆盘不能放在小圆盘上面。

通过递归调用上述步骤,可以将所有的圆盘从起始柱子移动到目标柱子。由于每次递归都会将一个圆盘从起始柱子移动到目标柱子,因此每个圆盘最多只会被移动一次,所以总共需要移动2^n - 1 次(n 表示圆盘的数量)。

3.C语言代码

#include <stdio.h>

void hanoi(int n, char A, char B, char C) {
    if (n == 1) {
        printf("Move disk 1 from %c to %c\n", A, C);
    } else {
        hanoi(n-1, A, C, B);
        printf("Move disk %d from %c to %c\n", n, A, C);
        hanoi(n-1, B, A, C);
    }
}

int main() {
    int n = 3; // 将3个盘子从A移动到C
    hanoi(n, 'A', 'B', 'C');
    return 0;
}

四.子集问题

1.问题描述

子集问题(Subset):给定一个含有n个元素的集合S,求出S的所有子集。可以使用递归实现。

2.思路分析

子集问题是一个基本的组合问题,它涉及到从一个给定的集合中选择一些元素组成新的集合。这个问题在计算机科学和数学中非常常见,解决子集问题可以帮助我们更好地理解组合问题和算法设计。

下面是一个简单的思路分析:

  1. 首先,我们需要确定如何表示集合。在大多数编程语言中,集合通常是用数组或列表来表示的。

  2. 接着,我们需要考虑如何生成所有可能的子集。一种常见的方法是使用递归算法。

  3. 对于递归算法,我们需要考虑以下几点:

    a. 基本情况:当集合为空时,只有一个空集。

    b. 递归情况:对于非空集合,我们可以选择将第一个元素包含在子集中或者不包含在子集中,然后对剩余的元素进行递归处理。

  4. 在递归过程中,我们需要维护一个当前子集的列表,并在每次递归结束后将其添加到结果集合中。

  5. 最后,我们可以返回结果集合,其中包含了原始集合的所有可能子集。

需要注意的是,由于子集问题的解空间非常大,因此在实际应用中,需要根据具体的场景进行优化,以减少时间和空间复杂度。

3.C语言代码

下面是一个使用C语言递归实现子集问题的示例代码:

#include <stdio.h>

void subset(int set[], int subset[], int n, int k, int start, int curr){
    if (curr == k) {
        printf("{");
        for (int i = 0; i < k; i++) {
            printf("%d ", subset[i]);
        }
        printf("}\n");
        return;
    }
    for (int i = start; i < n; i++){
        subset[curr] = set[i];
        subset(set, subset, n, k, i+1, curr+1);
    }
}

int main() {
    int set[] = {1, 2, 3};
    int n = sizeof(set)/sizeof(set[0]);
    int subset[n];
    for (int i = 0; i <= n; i++) {
        subset(set, subset, n, i, 0, 0);
    }
    return 0;
}

该代码中,subset函数使用了递归实现。其中,set表示原始集合,subset表示当前子集,n表示原始集合的大小,k表示当前子集的大小,start表示遍历起始位置,curr表示当前子集中元素的个数。

在函数中,首先判断当前子集是否已达到目标大小 k,如果已经达到则输出该子集,并返回上一层递归。否则,从遍历起始位置开始循环原始集合,将元素依次加入当前子集,并对剩余元素进行递归处理。

main 函数中,我们遍历所有可能的子集大小,并调用 subset 函数进行求解。最终结果会依次输出到标准输出。

五.归并排序

1.问题描述与分析

归并排序(Merge Sort)是一种基于分治思想的高效排序算法,通过将待排序数组递归地拆分为两个子数组,对每个子数组进行排序,然后将两个有序的子数组合并成一个有序的数组,最终得到排序完成的整个数组。

具体而言,归并排序的过程可以分为三个步骤:

  1. 分割:将待排序数组从中间位置划分为左右两个子数组,递归地对左右两个子数组进行分割,直到每个子数组只包含一个元素。
  2. 归并:将两个有序的子数组合并成一个有序的数组,直到所有子数组都被合并为一个完整的有序数组。
  3. 返回:返回排序完成的数组。

2.C语言代码

下面是用 C 语言递归实现归并排序的代码:

#include <stdio.h>
#include <stdlib.h>

void merge(int *arr, int l, int m, int r) {
    int i, j, k;
    int n1 = m - l + 1;
    int n2 = r - m;

    int L[n1], R[n2];

    for (i = 0; i < n1; i++)
        L[i] = arr[l + i];
    for (j = 0; j < n2; j++)
        R[j] = arr[m + 1 + j];

    i = 0;
    j = 0;
    k = l;
    while (i < n1 && j < n2) {
        if (L[i] <= R[j]) {
            arr[k] = L[i];
            i++;
        } else {
            arr[k] = R[j];
            j++;
        }
        k++;
    }

    while (i < n1) {
        arr[k] = L[i];
        i++;
        k++;
    }

    while (j < n2) {
        arr[k] = R[j];
        j++;
        k++;
    }
}

void mergeSort(int *arr, int l, int r) {
    if (l < r) {
        int m = l + (r - l) / 2;

        mergeSort(arr, l, m);
        mergeSort(arr, m + 1, r);

        merge(arr, l, m, r);
    }
}

int main() {
    int arr[] = {38, 27, 43, 3, 9, 82, 10};
    int n = sizeof(arr) / sizeof(arr[0]);
    
    mergeSort(arr, 0, n - 1);

    for (int i = 0; i < n; i++)
        printf("%d ", arr[i]);
    
    return 0;
}

在上面的代码中,merge 函数用于将两个有序子数组合并为一个有序数组,mergeSort 函数用于递归地分割和排序子数组。

六.说明

新星计划:数据结构与算法,@西安第一深情,创作打卡1!

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

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

相关文章

【HISI IC萌新虚拟项目】Package Process Unit模块整体方案·PART1

1.背景 网络中包是个重要概念,很多信息在网络中以包的形式传输。而传输介质容易受到外界环境干扰导致传输错误,因此需要在传输过程中进行数据校验、过滤等包处理。包处理和包转发是信息传输的重要处理方式,本芯片实现简单的包处理和包转发机制。 包处理过程中需要用到缓存…

神经网络:Zero2Hero 1 - Simple Language Model

Zero → \to → Hero : 1 实现了一个字符级中文语言模型&#xff0c;数据采用的是开源中文姓名数据集中的一部分&#xff0c;主要内容如下&#xff1a; 字符的预处理 统计频次计算字符对频次矩阵 实现一个简单的先验概率模型 从训练数据中计算字符的先验概率根据先验概率通过…

渗透测试--4.捕获和监听数据

目录 目录 1.监听捕获数据方法 2.kali监听捕获工具介绍 arpspoof arpspoof实战&#xff08;同一局域网断网实战&#xff09; driftnet 实战使用drifnet和工具捕获网络图片 1、扫描目标主机&#xff0c;开启ip转发 2、打开ettercap 3、进行arp欺骗&#xff1a; 4、使用drif…

Gap Hours,我在内卷和摆烂之间的折中选择

点击文末“阅读原文”即可参与节目互动 剪辑、音频 / 卷圈 运营 / SandLiu 卷圈 监制 / 姝琦 文案 / 粒粒 产品统筹 / bobo 场地支持 / 声湃轩天津录音间 一个名词解释&#xff1a; Gap Day&#xff0c;是工作和生活中为了从不好的状态中跳脱出来&#xff0c;享受了躺平…

技术支持内容

平台技术简介&#xff1a; 前端&#xff1a;采用Vue、uni-app等技术。 后端&#xff1a;采用Spring Boot 。 权限&#xff1a;采用Jwt&#xff0c;支持多终端认证系统。 邮箱&#xff1a; postmasterzhonghuisoft.cn 平台基础功能&#xff1a; 用户管理&#xff1a; 管理…

常数整数乘法优化

常数整数乘法优化 文章目录 常数整数乘法优化基于正则有符号数的常数整数乘法优化Example 1: 20 x 20x 20xExample 2: 153 x 153x 153xExample 3: 15 x 15x 15x正则有符号数编码 CSD二进制序列转CSD编码算法流程代码实现欢迎关注公众号【三戒纪元】 嵌入式机器学习或深度学习…

人工智能的机器人技术为啥那么强,对于未来意味着什么?

前言 人工智能技术的发展&#xff0c;推动了机器人技术的不断进步。机器人技术在工业、医疗、服务等领域发挥着越来越重要的作用。本文将详细介绍人工智能的机器人技术。 机器人技术的发展历程 机器人技术的发展可以追溯到20世纪50年代。当时&#xff0c;机器人主要用于工业生…

怎么给移动硬盘查错?移动硬盘查错能恢复数据吗

移动硬盘在长期使用或使用不当的情况下&#xff0c;可能会出现硬盘文件损坏或者出现坏道等问题&#xff0c;影响数据安全和文件操作。这时候&#xff0c;移动硬盘查错工具就派上用场了。它可以帮助用户发现移动硬盘中的问题&#xff0c;并且还可以对移动硬盘进行修复。 但是&a…

chatgpt赋能Python-python3_7怎么改颜色

Python3.7中如何改变颜色的方法 Python是一门广泛应用于各种领域的编程语言&#xff0c;其强大的数据分析能力和简单易用的语法得到了越来越多的开发者的青睐。在Python中&#xff0c;要想使文本在输出时带有颜色&#xff0c;可以使用ANSI转义序列进行操作。 什么是ANSI转义序…

国考省考行测:数量关系,消三法,比,分数,百分数,n倍

国考省考行测&#xff1a; 2022找工作是学历、能力和运气的超强结合体! 公务员特招重点就是专业技能&#xff0c;附带行测和申论&#xff0c;而常规国考省考最重要的还是申论和行测&#xff0c;所以大家认真准备吧&#xff0c;我讲一起屡屡申论和行测的重要知识点 遇到寒冬&am…

spring数据校验:Validation

目录 Spring Validation概述 通过Validator接口实现 Bean Validation注解实现 基于方法实现校验 实现自定义校验 Spring Validation概述 在开发中&#xff0c;我们经常遇到参数校验的需求&#xff0c;比如用户注册的时候&#xff0c;要校验用户名不能为空、用户名长度不超…

从眼中窥视:Google AI 模型如何通过眼睛预测你的年龄

新的模型可以通过分析眼部照片揭示衰老的秘密 近年来&#xff0c;谷歌一直在研究各种人工智能模型&#xff0c;可以分析眼睛&#xff08;内部和外部&#xff09;的图像并监测某些参数。正如之前提到的&#xff0c;开发能够从眼睛中提取信息的 AI 模型意味着能够以经济高效和无创…

Array-Deque-Queue等的区别

&#x1f50e;Deque&#xff08;双端队列&#xff09;: Deque 是 “double-ended queue” 的缩写&#xff0c;表示双端队列。它是一种可以在两端进行插入和删除操作的数据结构。你可以在队列的头部和尾部同时进行插入和删除操作。Deque 接口定义了这些操作的方法&#xff0c;如…

国际博物馆日|科技与文化的碰撞:大势智慧助力博物馆赋能美好生活

近年来&#xff0c;我国博物馆事业蓬勃发展&#xff0c;而科技与文博领域的深度融合&#xff0c;将继续成为博物馆事业高质量发展的助推器。作为连接过去、现在、未来的桥梁和新时代文化交流与传播的窗口&#xff0c;博物馆不仅是保护和传承人类文明的重要殿堂&#xff0c;也是…

网络优化干扰培训讲解

一、系统外干扰 1、信号放大器 1、特征&#xff1a;RB尖峰突起(类似于互调干扰&#xff0c;极少数会形成宽频干扰。信号放大器为目前FDD频段主要干扰源 2、影响范围&#xff1a;周边站点 3、干扰来源&#xff1a;用户私装信号放大器、黑直放站. 4、原因分析&#xff1a;放…

javaIO流之字节流

目录 1、字节输出流&#xff08;OutputStream&#xff09;2、FileOutputStream类2.1FileOutputStrea 的构造方法2.2FileOutputStream 写入字节数据2.3FileOutputStream实现数据追加、换行 3、字节流入流&#xff08;InputStream&#xff09;4、FileInputStream类4.1FileInputSt…

介绍自己的产品时,常犯的那些错

最近的一个轻咨询客户&#xff0c;在“全面提升组织产品能力”的项目中&#xff0c;正处于内部自学的“读书会”环节。 为了“用以致学”&#xff0c;而不是“学以致用”地读书&#xff0c;我给他们出了一道看起来很简单的题——介绍一下自己手头正在负责的产品。 前几天&#…

Java枚举

Java枚举 &#x1f37a;1 背景及定义&#x1f37a;&#x1f9c3;2 使用&#x1f9c3;&#x1f964;3 枚举优点缺点&#x1f964;&#x1f375;4 枚举和反射&#x1f375;&#x1f377;4.1 枚举是否可以通过反射&#xff0c;拿到实例对象呢&#xff1f;&#x1f377; ☕️5 总结…

正负压力精密控制在隐形牙齿矫正器成型机中的应用

摘要&#xff1a;真空压力热成型技术作为一种精密成型工艺在诸如隐形牙套等制作领域得到越来越多的重视&#xff0c;其主要特点是要求采用高精度的正负压力控制手段来抵消重力对软化膜变形的影响以及精密控制成型膜厚度。本文提出了相应的改进解决方案&#xff0c;通过可编程的…

Greenplum数据库系统架构

Greenplum数据库系统架构 Greenplum是一个纯软件的MPP数据库服务器&#xff0c;其系统架构专门用于管理大规模分析型数据仓库或商业智能工作负载。从技术上讲&#xff0c;MPP无共享架构是指具有多个节点的系统&#xff0c;每个节点都有自己的内存、操作系统和磁盘&#xff0c;…